Когда использовать указатель на класс, а когда просто создавать его экземпляр как переменную - PullRequest
11 голосов
/ 05 января 2011

Я вроде как смущен этим. Лучшее, что я смог найти, - это прочитать учебник cplusplus.com и все, что они могут сказать об указателях на классы.

«Совершенно верно создавать указатели, указывающие на классы. Мы просто должны учитывать, что после объявления класс становится допустимым типом, поэтому мы можем использовать имя класса в качестве типа для указателя»

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

Будут оценены общие примеры; но более конкретно, связанных с программированием GUI. Там, где я впервые столкнулся.

QGridLayout *mainLayout = new QGridLayout;
mainLayout->addWidget(nameLabel, 0, 0);
mainLayout->addWidget(nameLine, 0, 1);
mainLayout->addWidget(addressLabel, 1, 0, Qt::AlignTop);
mainLayout->addWidget(addressText, 1, 1);

Почему бы и нет

QGridLayout mainLayout
mainLayout.addWidget
...

(он не компилируется, если я изменяю пример кода на него и пробую его, но вы понимаете)

Заранее спасибо

Ответы [ 5 ]

10 голосов
/ 05 января 2011

Хороший способ подумать о том, когда распределять по стеку (не указатель), а не по назначению кучи (указатель) объекта, - это думать о том, как долго вы хотите, чтобы этот объект жил.Если вы поместите объект в стек как локальную переменную, он будет очищен и перестанет существовать, как только функция вернется.Если вы хотите, чтобы объект пережил вызов функции, который его создал, поместите его в кучу.

На примере компоновки сетки я считаю, что указатель версии более уместен, поскольку после вызова функции, которая создаетмакет возвращается, вы все еще хотите, чтобы макет лежал вокруг.В противном случае макет будет существовать только до тех пор, пока функция работает.

2 голосов
/ 05 января 2011

Одной из веских причин является полиморфизм и динамическая диспетчеризация. Имея указатель, объявленный на тип базового класса, и назначая его экземпляру подтипа, вы можете вызывать разные версии метода. В приведенных выше примерах, возможно, существует некоторый базовый тип (может быть, QTLayout?), С которым указатель может быть объявлен.

Другая причина - это ситуация, когда вы хотите, чтобы ваш объект «жил» за пределами метода, в котором он объявлен. Ваш второй пример размещен в стеке и будет освобожден при выходе.

1 голос
/ 05 января 2011

Реальный вопрос не в использовании указателей, а в динамическом размещении.Динамическое размещение объекта (с помощью new) позволяет вам контролировать время жизни объекта.Если вы хотите создать объект в функции, но не хотите, чтобы он прекратил свое существование, как только функция будет завершена, тогда динамическое размещение для вас.

Обычно вы увидите указатели, указывающие на динамически-распределенные объекты (так как это лучший способ справиться с ними, ссылки являются неуклюжей альтернативой);тем не менее, вы также можете иметь указатель на объект с автоматической продолжительностью хранения:

QGridLayout mainLayout;
QGridLayout* ptr = &mainLayout;
ptr->addWidget(nameLabel, 0, 0);
ptr->addWidget(nameLine, 0, 1);
ptr->addWidget(addressLabel, 1, 0, Qt::AlignTop);
ptr->addWidget(addressText, 1, 1);

^ В этом примере я использую автоматическое хранение (создавая объект как «нормальную переменную», как вы положилиэто), поэтому объект будет уничтожен в конце области видимости вмещающего блока (возможно, в конце функции или, возможно, в условном (if) блоке), но при этом все еще будет использоваться указатель с ним!

Надеюсь, это поможет.

0 голосов
/ 05 января 2011

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

0 голосов
/ 05 января 2011

Является ли QGridLayout классом?Второй должен работать нормально, если вы исправили опечатки.Вы сказали, что это не компилируется.Должны ли мы догадываться об ошибке?

Создание объекта как локального экземпляра - это нормально.Единственная потенциальная проблема, если класс большой, так как это приводит к чрезмерному использованию стекового пространства.

Обратите внимание, что объект может выделять всю необходимую ему память, что не повлияет на его размерстек.

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