c++ - 使用模板的继承和转换未按预期工作

标签 c++ templates inheritance casting polymorphism

我一直在研究模板和继承,但是在对基类执行强制转换时使用带有模板参数的虚函数成员有些奇怪。他们似乎使用“直接继承”工作,但如果我稍后“推迟”继承则不行。

一些代码来说明:

例子[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有关吗?

最佳答案

即使 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(); }
};

关于c++ - 使用模板的继承和转换未按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54213076/

相关文章:

c++ - C++ 中的继承成本

c++ - 如何配置在 CLion 中构建项目的方式?

c++ - 比较不同的 vector 迭代器并从第一个 vector 中删除元素

PHP html 电子邮件,使用 html 模板

c++ - 模板成员函数的编译器错误

java - opencsv不导出父类的属性

c++ - 如何使用 C++ 代码设置核心文件名?

c++ - 编译 Mongodb 3.6.5 以插入到 Docker 镜像中

c++ - 模板特化容器

C#:父类(super class)在向上转换后仍然有子类信息