Разве это плохо для воссоздания стека объекта после введения в класс в качестве указателя? - PullRequest
0 голосов
/ 24 января 2020
// Example program
#include <iostream>

class Foo{

public:  
  Foo(int a):a(a){}
  void print(){
      printf("%d\n",a);
  }

private: 
  int a;

};

class Bar{
public:
  Bar(Foo* foo):foo(foo){}
  void print(){
    foo->print();
  }

private:
  Foo* foo;
};

int main()
{
  Foo f = {10};
  Bar b(&f);
  b.print();
  f = {20};
  b.print();
}

В приведенном выше коде объект Foo, совместно используемый с объектом Bar, может быть воссоздан без уведомления Bar об этом. Представьте, что мне нужно добавить объект бара в третий класс. Теперь я могу обновить зависимость foo, не создавая новый объект bar и третий класс.

Этот шаблон обычно используется или нет, и он нарушает некоторые из принципов OOP?

Ответы [ 3 ]

1 голос
/ 24 января 2020

Я не думаю, что код делает то, что вы думаете, что он делает. Я добавил конструкторы по умолчанию и назначил / операторы для вашего класса Foo с некоторыми регистрациями, чтобы увидеть, что происходит. Эти конструкторы автоматически добавляются компиляторами, если вы не отключите их явно. Смотрите вывод здесь .

Что происходит в

f = {20};

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

В этом случае это эквивалентно

f.a = 20;  // Assuming we make a public.

В заключение. Если вы используете только для изменения полей в существующем экземпляре (в данном случае через операторы присваивания). Тогда все должно работать нормально. Это не обязательно лишает законной силы принципы OOP, если только у вас нет предположений, что Bar.foo является постоянным или не изменяется. Обычно это называется композицией, и она довольно распространена (ваш пользовательский интерфейс будет содержать различные экземпляры кнопок, которые могут быть изменены из других источников).

Если вы ожидаете изменить реализацию (скажем, Foo - это виртуальный класс, и вы хотите другой вывод, который нужно заменить), тогда в вашем коде вам понадобится Foo* f = new Foo(10);. У вас будет копия указателя в b, и назначение создаст новый класс, который не будет обновляться в b (что-то вроде f = new FooDerived(20);.

. Чтобы он работал, вам нужен провайдер класс (это шаблон OOP). Это будет то, что даст вам Foo. Самый простой будет Foo**. Но, вероятно, лучше иметь что-то более настраиваемое.

Тем не менее, для любой серьезной работы старайтесь держаться подальше от голых указателей (Foo*). Используйте unique_ptr или shared_ptr в зависимости от ситуации, чтобы избежать множества проблем в будущем.

0 голосов
/ 24 января 2020

Является ли этот шаблон широко используемым или нет и нарушает ли он некоторые из принципов OOP?

Да, это довольно распространенное явление, и в вашем примере это нормально.

Вы должны быть осторожны, чтобы убедиться, что f остается живым в течение всего времени жизни b, как в вашем примере. Если вы хотите скопировать b, вам также необходимо убедиться, что копия не устарела f.

Приятной особенностью локальных переменных функции func является то, что они переживают любые локальные переменные функций, которые вызывает func. Таким образом, локальные переменные main живут (почти) для всей программы, только глобальные переменные переживают их.

0 голосов
/ 24 января 2020

Этот шаблон обычно используется или нет и нарушает ли он некоторые OOP принципы?

Я бы сказал, что такую ​​структуру следует использовать осторожно.

На самом деле, в Bar вы просто копируете значение указателя. Но если указанный Foo, созданный в стеке, выходит из области видимости, то Bar хранит висячий указатель.

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

Плохо ли воссоздавать объект стека после введения в класс в качестве указателя?

На самом деле, как упоминалось @ DanielLangr , у вас не было «воссоздав» объект, вы просто переназначили его содержимое, поэтому время жизни объекта не закончилось. В твоем случае ты все еще в порядке.

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