Возникли проблемы с пониманием классов C ++ - PullRequest
0 голосов
/ 01 мая 2018
class myClass
{
private:
    struct myStruct
    {
        int width = 0;
    };
public:
        myClass();
        void changeValue();
};

myClass::myClass()
{
    myStruct aStruct;
    aStruct.width = 24;
}

void myClass::changeValue()
{
    aStruct.width = 23;
}

Я сделал простой код выше для тестирования классов. В функции-член changeValue я получаю сообщение о том, что aStruct не определен. Но я не очень понимаю, почему он говорит, что он не определен. Ранее, когда я работал с классами, этот код работал нормально. Разница между тогда и сейчас заключается в том, что в конструкторе классов я использовал указатели. Так работает ли этот тип кода только для указателей, а не для структур?

Причина, по которой я хочу, чтобы это работало, состоит в том, что было бы очень полезно иметь этот "глобальный" объект, принадлежащий классу, который является структурой.

Ответы [ 2 ]

0 голосов
/ 01 мая 2018

Прежде чем ваш вопрос будет раскрыт, вы должны понять, что все в {} находится внутри этих скобок, поэтому ваша проблема в том, что у вас есть:

myStruct aStruct;

внутри конструктора. Таким образом, aStruct является локальной переменной для конструктора. Чтобы исправить ваш код, переместите его чуть ниже struct определение.

class myClass
{
private:
    struct myStruct
    {
        int width = 0;
    };

    // MOVE IT HERE
    myStruct aStruct;
public:
    myClass();
    void changeValue();
};

myClass::myClass()
{
    aStruct.width = 24;
}

void myClass::changeValue()
{
    aStruct.width = 23;
}

Теперь все функции-члены имеют доступ к aStruct.

0 голосов
/ 01 мая 2018

Это не проблема с "пониманием классов". Вы должны вернуться и понять, что такое «область действия», которая является одной из основных концепций языка C ++.

 myStruct aStruct;

принадлежит области действия функции-члена myClass::myClass() и перестает существовать, когда заканчивается выполнение этой функции. Это совершенно другая область, там не существует переменной aStruct.

void myClass::changeValue() 
{
     aStruct.width = 23; // aStruct doesn't exist in any available scope 
}

Теперь о декларациях:

class myClass
{
private:
    struct myStruct
    {
        int width = 0;
    };

Этот код не объявляет хранилище структуры внутри класса myClass. Он объявляет тип члена myStruct (который является типом класса) внутри класса myClass.

(Будьте осторожны с этим соглашением об именах, оно очень запутанно. Рекомендуется использовать заглавные буквы только для членов. Классы рекомендуется использовать только строчные или начинающиеся с заглавной буквы.)

class myClass
{
private:
    struct myStruct
    {
        int width = 0;
    };

    myStruct aStruct; // myClass got field aStruct

public:
    myClass() : aStruct {24} {}
    void changeValue();
};

aStruct здесь относится к закрытой части области видимости класса, которая доступна для всех членов этого класса. myStruct также объявлен как закрытый, поэтому не может использоваться вне класса, будь то в дочернем классе или просто во внешней области видимости.

myClass() : aStruct {24} {}

Это нетривиальный (определяемый пользователем) конструктор со списком инициализаторов. aStruct является полем этого класса, поэтому его можно инициализировать значением, подобным этому. Отличается от этой формы

myClass() 
{
   aStruct.width = 24;
}

В последнем случае aStruct будет инициализирован сначала (с 0 в поле ширины, как вы указали), и будет вызван его конструктор, затем конструктор myClass изменит значение своего поле до 24.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...