Динамическое связывание shared_ptr - PullRequest
0 голосов
/ 27 ноября 2018

Я пытаюсь реализовать что-то, следуя шаблону декоратора, но я не могу получить от shared_ptr такое же поведение во время выполнения, которое я могу получить с помощью обычных указателей.У меня есть базовый класс I (интерфейс) с виртуальным методом, затем я извлекаю из него два класса:

  • class A (компонент), который будет содержать некоторые данные
  • класс B (декоратор), который получается из I , а также содержит указатель на него и реализует некоторое дополнительное поведение.У меня есть конструктор, который инициализирует указатель на определенный I (или производный) объект.

Затем я хочу иметь возможность построить B объект с указателем, указывающим на A , поэтому при вызове общих методов я вызываю A единицы, а не I единицы.

Я могу сделать это, если сделать указатель в B обычным способом (в примере кода см. Класс B_basic и объект bb в основном).

Но если я сделаю этот указатель как shared_ptr до I , он вызовет метод из I , даже если я создаю его, указывая на фактический A (в коде см. Класс B_shared и объект bs )

class I {

   public:
      virtual void method() {cout<<"I\n";}
      virtual ~I() = default;
};

class A : public I {
   public:
      virtual void method() {cout<<"A\n";}
};

class B_shared : public I {
   public:
      shared_ptr<I> shared_pointer;
      B_shared(const I& i) : shared_pointer(make_shared<I>(i)) {}
      virtual void method() { 
         cout<<"B_shared > ";

         shared_pointer->method();
      }
};

class B_basic : public I {
   public:
      I* basic_pointer;
      B_basic(I* i) : basic_pointer(i) {}
      virtual void method() { 
         cout<<"B_basic > ";

         basic_pointer->method();
      }
};


int main() { 
   A a;
   B_shared bs(a);
   B_basic bb(&a);
   bs.method(); // B_shared > I
   bb.method(); // B_basic > A
}

Что я делаю не так?

1 Ответ

0 голосов
/ 27 ноября 2018

Это нарезка объектов.

В следующей строке вы делаете копию экземпляра i типа A для типа I.Таким образом, исходный тип A разделен на базовый тип I.

shared_pointer(make_shared<I>(i)) 

В версии необработанного указателя basic_pointer(i) вы сохраняете сам указатель, без среза.

...