【问题标题】:Inheritance and casting with templates not working as expected使用模板的继承和强制转换未按预期工作
【发布时间】:2019-06-10 07:18:15
【问题描述】:

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

一点代码来说明:

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

【问题讨论】:

  • CastExA&lt;int&gt;* a3 = (CastExA&lt;int&gt;*) a2; - 你不能使用 C 风格的演员阵容,你需要在这里dynamic_cast
  • 理想情况下是的,但我知道类型将是 CastExA* 所以应该可以使用它。无论如何,我也尝试动态转换它,但结果相同
  • 一般提示:永远不要在 C++ 中进行 C 样式转换。如果您需要这样做,这通常是一个危险信号,表明您做错了。
  • 是的,我应该使用 static_cast,我同意
  • 密切相关,可能被骗:stackoverflow.com/questions/19528338/…

标签: c++ templates inheritance casting polymorphism


【解决方案1】:

即使CastExC 继承了CastExA&lt;int&gt;CstExBh()CstExB 中的定义也不会覆盖CastExA&lt;int&gt;h() 的“定义”,因为CastExA&lt;int&gt; 和@987654329 @ 不相关。如果您尝试这样做:

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

【讨论】:

    【解决方案2】:

    CastExC 中没有 h()。也许这就是原因。

    注意:CastExACastExB 不相关。

    【讨论】:

    • 该死的确实是这样......一如既往的最简单的解决方案......谢谢
    猜你喜欢
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多