Как вернуть структуру из класса, в котором она определена?

#c #c 11

#c #c 11

Вопрос:

Я хочу вернуть копию struct из функции открытого класса, и я определяю эту структуру внутри этого класса как закрытый член.

Возможно ли вернуть эту структуру для любого другого типа пользовательских данных?

Рассмотрим этот простой пример:

 class Test {
private:
    struct sTest {
        int i = 1;
    }_sTest;
public:
    sTest GetStruct() {
        return _sTest;
    }
};
 

затем после того, как я создам объект этого класса:

 Test cTest;
 

как я могу вызвать

  cTest.GetStruct()
 

чтобы получить

  _sTest
 

?

Комментарии:

1. Проблема в том, что пользователь, который вызывает GetStruct(), не имеет доступа к закрытым элементам, и он / она не знает реализацию структуры.

2.Как вы ожидаете, что вызов кода приведет к k теперь, что делать с sTest возвращенным by GetStruct , если имя sTest является закрытым? Технически вы могли бы сделать что-то вроде auto something = sTest.GetStruct(); , потому что только имя sTest является закрытым (демонстрация здесь), но… почему вы хотите это сделать? Если sTest предполагается, что an имеет значение для вызывающего кода, сделайте его частью открытого интерфейса класса.

3. если я сделаю STest общедоступным, он не будет инкапсулирован. Все, что я хочу сделать, это прочитать данные, которые хранятся в частной структуре внутри класса. Есть ли лучшие способы?

4. также у меня есть дочерние классы, производные от CTest , которые перегружают GetStruct() и имеют свои собственные реализации структуры STest, поэтому мне нужно сделать STest уникальным для каждого дочернего класса

5. Если вы возвращаете an sTest в общедоступной функции и ожидаете, что вызывающий код сможет работать непосредственно с an sTest , вы уже ничего не «инкапсулируете», потому что эти детали реализации должны быть известны. Возможно, выяснить, какие конкретные данные, хранящиеся в an sTest , должны быть доступны пользователям класса, и написать функции, которые их возвращают?

Ответ №1:

Вы можете использовать auto для хранения объекта.

Ниже приведен пример кода. Посмотрите это здесь в действии:

 #include <iostream>
using namespace std;

class Test {
private:
    struct sTest {
        int i = 1;
    }_sTest;
public:
    sTest GetStruct() {
        return _sTest;
    }
};



int main()
{
    Test a;
    auto obj = a.GetStruct();
    
    cout<< obj.i <<"nDone!!!n";
    return 0;
}
 

Вывод:

 1
Done!!!
 

Примечание: это нормально и для других компиляторов. Проверьте здесь и другие компиляторы.

Комментарии:

1. спасибо, да, я уже разобрался с этим обходным путем, но я сомневался, безопасно ли это.

2. @hgrev Я проверил компиляторы, доступные на coliru.stacked-crooked.com и это кажется прекрасным. Ни один из компиляторов не жаловался.

Ответ №2:

На всякий случай, если вы не хотите объявлять свою структуру в своем классе:

 // not necessarily a member function
auto GetStruct()
{
  struct sTest {
        int i = 1;
    };
  return sTest();
}

using test_t = decltype(GetStruct()); // you can make an alias for an anonymous struct.
auto test = GetStruct();
 

Комментарии:

1. спасибо, интересно!

Ответ №3:

Поскольку частный класс недоступен из теста класса снаружи, используйте ключевое auto слово .

 auto test = cTest.GetStruct();
 

Ответ №4:

Да, это совершенно безопасно. Это похоже на любой другой тип данных. С помощью auto вы просто указываете компилятору угадать, какой будет переменная.