C ++ получает поведение polymorphi c с членами класса и умными указателями - PullRequest
0 голосов
/ 26 марта 2020

У меня есть следующие настройки класса:

class A {
public:
  virtual void show() { // "show A" }
}

class B : A {
public:
  void show() override { // "show B"}
}

class MainClass {
public:
  MainClass(const A &myA) : myPolymorphicClass(std::make_shared<A>(myA)) {}
  void doShow() {
    myPolymorphicClass.show();
  }

private:
  std::shared_ptr<A> myPolymorphicClass;
}

int main {
   A myA;
   B myB;
   MainClass myAClass(myA);
   myClass.doShow(); // Will print "show A"

   MainClass myBClass(myB);
   myClass.doShow(); // Will also print "show A"
}

Я хочу, чтобы вызывался соответствующий show (), но он не совсем работает. Я знаю, это потому, что я делаю make_shared для A, который будет указывать на show () A, а не на B, но если я сделаю make_shared для B, у меня возникнет противоположная проблема. Как я могу настроить этот класс, чтобы получить поведение polymorphi c, которое я хочу?

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

Большое спасибо!

1 Ответ

1 голос
/ 26 марта 2020

Ваша проблема с

MainClass(const A &myA) : myPolymorphicClass(std::make_shared<A>(myA)) {}

Здесь вы используете std::make_shared<A>(myA), что означает, что независимо от того, на что ссылается myA, вы только создадите часть A в указателе. Это означает, что вы всегда будете вызывать A версию функции, потому что все, что у вас есть, это A. Вам нужен шаблон типа

template <typename T>
MainClass(const T &myA) : myPolymorphicClass(std::make_shared<T>(myA)) {}

И теперь вы создадите указатель на производный класс, который будет храниться в myPolymorphicClass. Если вы хотите даже добавить SFINAE в шаблон, чтобы ограничить T производным от A, например

template <typename T, std::enable_if_t<std::is_base_of_v<A,T>, bool> = true>
MainClass(const T &myA) : myPolymorphicClass(std::make_shared<T>(myA)) {}

Все это работает в этом живом примере

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