Наследование и приведение типов с шаблонами не работают должным образом - PullRequest
0 голосов
/ 16 января 2019

Я поигрался с шаблоном и наследованием, но есть что-то странное в использовании членов виртуальной функции с параметрами шаблона при выполнении приведения к базовому классу. Кажется, они работают с использованием «прямого наследования», но не тогда, когда я «отложу» наследование позже.

Немного кода для иллюстрации:

Пример [1]

struct CastExBase
  {
  virtual void f() {}
  };

template<class RT>
struct CastExA : CastExBase
  {
  void f() {std::cout << "CastExA" << std::endl;}
  virtual void g() {std::cout << "g - A" << std::endl;}
  virtual RT h() {std::cout << "h - A" << std::endl;}
  };

struct CastExB
  {
  void execF() {std::cout << "CastExB" << std::endl;}
  void g() {std::cout << "g - B" << std::endl;}
  int h() {std::cout << "h - B" << std::endl;}
  };

struct CastExC :
    public CastExA<int>,
    protected CastExB
  {
  void f() override
    {
    (static_cast<CastExB*>(this))->execF();
    }

  void g() override
    {
    (static_cast<CastExB*>(this))->g();
    }
  };

Контрольный пример:

  CastExBase* a2 = new CastExC();
  CastExA<int>* a3 = (CastExA<int>*) a2;
  a3->g(); // This prints g - B as expected
  a3->h(); // This prints h - A ... why???

Почему a3-> h () не печатает h - B?

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

Пример [2]

struct CastExDBase
      {
      };

    template<class T>
    struct CastExD : CastExDBase
      {
      virtual T f() {std::cout << "CastExD" << std::endl;}
      };

    struct CastExE : CastExD<int>
      {
      int f() {std::cout << "CastExE" << std::endl;}
      };

Контрольный пример:

  CastExDBase* d1 = new CastExE();
  CastExD<int>* d2 = (CastExD<int>*) d1;
  d2->f(); // This prints CastExE as expected

Это связано с UB?

Ответы [ 2 ]

0 голосов
/ 16 января 2019

Даже если CastExC наследует оба CastExA<int> и CstExB, определение h() в CstExB не будет переопределять «определение» h() в CastExA<int>, поскольку CastExA<int> и CstExB не связаны Если вы попытаетесь сделать это:

CastExBase* a2 = new CastExC();
CastExC* a3 = (CastExC*) a2;
a3->h();

Вы получите неоднозначный запрос на h(). Если вы хотите перегрузить, вам нужно сделать это вручную:

struct CastExC: protected CastExB, public CastExA<int> {
    virtual int h() override { return CastExB::h(); }
};
0 голосов
/ 16 января 2019

Нет h() в CastExC. Может быть, поэтому.

Примечание: CastExA и CastExB не связаны.

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