使用模板无法进行预期的继承和转换

时间:2019-01-16 08:37:37

标签: 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有关吗?

2 个答案:

答案 0 :(得分:5)

即使CastExC继承了CastExA<int>CstExBh()CstExB的定义也不会覆盖{{1}的“定义” h()中的},因为CastExA<int>CastExA<int>不相关。如果您尝试这样做:

CstExB

您将收到一个对CastExBase* a2 = new CastExC(); CastExC* a3 = (CastExC*) a2; a3->h(); 的模糊请求。如果要过载,则需要手动执行此操作:

h()

答案 1 :(得分:4)

java -jar -Dapp.home="." axian-oxalys.jar中没有h()。也许就是这个原因。

注意:CastExCCastExA无关。