Указатель C++ на класс

Я был ликующим для наблюдения пользы gKrellm для 12,04. Его не совсем столь же роскошный как окна 7 виджетов, но сделает почти весь одинаковый вещи.

Просто открывают центр программного обеспечения и ищут gkrellm.

я знаю, что у них есть погодный плагин, но afaik, там не проверка Твиттера.

19
задан James Hay 16 April 2015 в 00:45
поделиться

6 ответов

Первый случай:

Display *disp = new Display();

Выполняет три действия:

  1. Создает новую переменную disp с типом Display * , что является указателем на объект типа Display , а затем
  2. размещает новый объект Display в куче, а
  3. устанавливает disp , чтобы указать на новый объект Display .

Во втором случае:

Display *disp; disp = new GzDisplay();

Вы создаете переменную disp с типом Display * , а затем создайте в куче объект другого типа , GzDisplay и назначьте его указатель на переменную disp .

Это будет только работать если GzDisplay является подклассом Display. В данном случае это выглядит как пример полиморфизма .

Кроме того, чтобы ответить на ваш комментарий, нет никакой разницы между объявлениями:

Display* disp;

и

Display *disp;

Однако из-за того, как работают правила типа C, есть разница между:

Display *disp1;
Display* disp2;

и

Display *disp1, disp2;

Потому что в последнем случае disp1 - это указатель на объект Display , вероятно, размещенный в куче, тогда как disp2 является фактическим объектом, вероятно, размещенным в стеке. . То есть, хотя указатель, возможно, является частью типа, синтаксический анализатор вместо этого свяжет его с переменной.

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

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

19
ответ дан 30 November 2019 в 04:25
поделиться
// implicit form
// 1) creates Display instance on the heap (allocates memory and call constructor with no arguments)
// 2) creates disp variable on the stack initialized with pointer to Display's instance
Display *disp = new Display();

// explicit form
// 1) creates Display instance on the heap (allocates memory and call constructor with no arguments)
// 2) creates disp variable on the stack initialized with pointer to Display's instance
Display* disp(new Display());

// 1) creates uninitialized disp variable on the stack
// 2) creates Display instance on the heap (allocates memory and call constructor with no arguments)
// 3) assigns disp with pointer to Display's instance
Display *disp;
disp = new Display();

Разница между явной и неявной формами инициализации будет видна только для сложных типов с конструкторами. Для типа указателя (Display *) нет никакой разницы.

Чтобы увидеть разницу между явной и неявной формами, просмотрите следующий пример:

#include <iostream>

class sss
{
public:
  explicit sss( int ) { std::cout << "int" << std::endl; };
  sss( double ) { std::cout << "double" << std::endl; };
  // Do not write such classes. It is here only for teaching purposes.
};

int main()
{
 sss ddd( 7 ); // prints int
 sss xxx = 7;  // prints double, because constructor with int is not accessible in implicit form

 return 0;
}
5
ответ дан 30 November 2019 в 04:25
поделиться
Display *disp = new Display();

Эта строка кода создает переменную типа Display * и инициализирует ее адресом вновь созданного объекта.

Display *disp;        // (1)
disp = new Display(); // (2)

Первая строка кода просто объявляет переменную типа Display *. В зависимости от настроек вашего компилятора - указатель может быть инициализирован, а может и нет. По сути, его следует рассматривать как недопустимый указатель, который не обязательно указывает на NULL.

Вторая строка присваивает указателю адрес вновь созданного объекта.

Результат обоих фрагментов кода будет одинаковым.

При включенной оптимизации любой компилятор должен генерировать одну и ту же сборку для них обоих. С отключенной оптимизацией и с некоторой генерацией кода отладки - оба фрагмента могут генерировать совершенно другой код - во втором случае, указатель сначала будет инициализирован значением, используемым компилятором для неинициализированных указателей (что-то вроде 0xDEADBEEF или 0xEFEFEFEF - и легко узнаваемый образец). В первом сниппете - указатель всегда должен инициализироваться адресом объекта вне зависимости от настроек. Обратите внимание, что это зависит от компилятора - некоторые компиляторы могут делать то, что я говорю, некоторые могут делать что-то совершенно другое.

1
ответ дан 30 November 2019 в 04:25
поделиться

Вы нашли четыре способа записать одно и то же.

Примеры 1 ( Display * disp… ) и 3 ( Display * disp… ]) идентичны; расстояние вокруг * не имеет значения. Однако стиль 1 часто предпочтительнее, потому что:

Display* disp1, disp2;

на самом деле означает:

Display *disp1, disp2;

то есть, disp2 не является указателем.

Пример 2 (разделение на две строки) имеет тот же эффект и, вероятно, будет скомпилирован в тот же код. Четвертый пример, использующий синтаксис инициализатора, также делает то же самое.

Обратите внимание, что если бы это были классы, а не указатели, могла бы быть разница в поведении и скорости.

1
ответ дан 30 November 2019 в 04:25
поделиться

Создается объект типа Display и объект типа Gz Display , это намеренно или это опечатка?

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

0
ответ дан 30 November 2019 в 04:25
поделиться

1) Экземпляр GzDisplay создается во 2-м варианте, тогда как в 1-м варианте созданный экземпляр имеет тип Display (я предполагаю, что GzDisplay является подклассом Display, верно?); 2) Кроме того, что 1-й короче, во 2-м disp имеют неопределенное значение до тех пор, пока ему не будет присвоено новое значение GzDisplay (). Второй вариант дает вам шанс случайно забыть об этом и вставить код, использующий disp, перед его инициализацией.

0
ответ дан 30 November 2019 в 04:25
поделиться
Другие вопросы по тегам:

Похожие вопросы: