Я изучаю C ++ как хобби и борюсь с использованием «new» для динамического создания объекта класса. Я читал, что динамически создаваемые классы не теряют своей области видимости, но это не похоже на мой простой пример.
При выполнении значение ‘testValue1’ устанавливается равным 555 в конструкторе и печатается. Когда элемент управления возвращается в main, «testvalue», к сожалению, устанавливается в 0 (или не определен — не уверен). Я могу установить значение внутри main, и значение должным образом поддерживается как внутри main, так и в цикле for.
Проблема: я не понимаю, почему инициализированное значение 555 не поддерживается, когда управление возвращается к основному. Я знаю, что делаю что-то не так или неправильно понимаю область действия для динамически назначенного объекта класса … любая помощь приветствуется. Вот пример кода:
//main.cpp
#include <iostream>
using namespace std;
class generalVars
{
private:
public:
//data attributes
int testValue1;
//constructor
generalVars()
{
cout << "I am in general vars constructor" << endl;
int testValue1= 555;
cout << "testValue1 has been set " << testValue1 << endl;
}
~generalVars(void)
{
cout << "I am in general vars destructor" << endl;
};
};int main(int argc, char *argv[])
{
cout << "I am in Main" << endl;
generalVars* myGeneralVars = new generalVars; //create on heap
cout << "Main1 testvalue1 = " << myGeneralVars->testValue1 << endl;
myGeneralVars->testValue1 = 777;
cout << "Main2 testvalue1 = " << myGeneralVars->testValue1 << endl;
for (int i=0; i<= 3; i++)
{
cout << "Inside while loop..." << endl;
cout << "Main3 " << i << " testvalue1 = " << myGeneralVars->testValue1 << endl;
}
delete myGeneralVars; //delete from heap
return 0;
}
Это утверждение:
int testValue1= 555;
объявляет локальная переменная, отличается от данных члена с тем же именем.
Так что это не меняет значение члена.
Вместо этого сделайте, например,
testValue1= 555;
Или используйте список инициализатора памяти конструктора, например так:
generalVars()
: testValue1( 555 )
{
cout << "I am in general vars constructor" << endl;
cout << "testValue1 has been set " << testValue1 << endl;
}
Вы определили другую переменную в конструкторе generalVars и значение init для 555, чтобы инициализировать член testValue1, вам не нужно определять его снова в конструкторе.
Обновить
generalVars()
{
cout << "I am in general vars constructor" << endl;
int testValue1= 555; // this defines another testValue1 variable. it's different from member testValue1
cout << "testValue1 has been set " << testValue1 << endl;
}
в
generalVars()
{
cout << "I am in general vars constructor" << endl;
testValue1= 555; // Note, removed int
cout << "testValue1 has been set " << testValue1 << endl;
}
Происходят две вещи:
1) Вы повторно объявляете testValue1 здесь, помещая int перед:
generalVars()
{
cout << "I am in general vars constructor" << endl;
int testValue1= 555; //right here!
cout << "testValue1 has been set " << testValue1 << endl;
}
Это скрывает собственный экземпляр класса testValue1 с новой уникальной переменной с тем же именем. Вы можете ссылаться на оба, как это:
generalVars()
{
cout << "I am in general vars constructor" << endl;
int testValue1= 555; //note, still has int
cout << "testValue1 has been set " << testValue1 << endl;
cout << "this->testValue1 has not been set and is " << this->testValue1 << endl;
this->testValue1 = 555; //note, this->
cout << "this->testValue1 has been set " << this->testValue1<< endl;
}
Или вы можете избежать столкновения имен и ссылаться на него обычно:
generalVars()
{
cout << "I am in general vars constructor" << endl;
testValue1= 555; //note, no int. This is identical to this->testValue1
cout << "testValue1 has been set " << testValue1 << endl;
}
Далее это не совсем проблема, но следует отметить:
Вам не нужно большую часть времени распределять вещи с помощью new в C ++. Вы должны предпочесть стекированные объекты
generalVars myObject;
вместо:
generalVars *myObject = new generalVars();
...
delete myObject;
Или, в случаях, когда вы хотите создать выделенный объект кучи:
auto myObject = std::make_unique<generalVars>();
Или, если вам нужно несколько ручек:
auto myObject = std::make_shared<generalVars>();
Примеры unique_ptr и shared_ptr не требуют явного удаления. Распределение кучи будет удалено, когда объект указателя выйдет из области видимости. Это особенно помогает с безопасностью исключений.