【问题标题】:Inheritance with CRTPCRTP 继承
【发布时间】:2010-02-24 10:35:53
【问题描述】:

我有这 3 个课程。

class A  
{  
    public:  
        virtual void Func() = 0;  
};

template<class T>  
class B : public A  
{  
    public:  
        void Func()  
        {  
            cout << "In B" << endl;  
            static_cast<T*>(this)->Func();  
        }  
};  

class C : public B<C>  
{  
    public:  
        void Func()  
        {  
            cout << "In C" << endl;  
        }  
};  

而且,我这样做:

int main(int argc, char **argv)  
{  
    A *a = new C;  
    a->Func();  

    return 0;  
}  

它会打印:“In C”。

如果我这样做,

int main(int argc, char **argv)  
{  
    B<C> *a = new C;  
    a->Func();  

    return 0;  
}  

它再次打印“In C”

发生了什么事?

【问题讨论】:

  • 您希望它打印什么?
  • 在第二种情况下“In B”然后是“In C”?
  • 代码无法编译。修复 B::Func 中的静态转换或解释您想要实现的目标。
  • 这段代码编译... g++ (SUSE Linux) 4.3.2

标签: c++ overloading crtp


【解决方案1】:

您正在调用重载该函数的 C 类对象的虚成员函数。它调用 C 类中的函数。

此外,这不是 CRTP,因为模板化的类 B 不继承自类模板参数。

【讨论】:

  • 原始代码(在您修复之前)缺少很多必要的东西,所以很难说出最初的意思。也许 CRTP 的东西也意外丢失了……
  • 这不是 CRTP 是什么意思?你的意思是 B 应该从 C 继承吗?
  • 没有。 CRPT 表示 B 应该继承自 T。
【解决方案2】:

Func 是虚拟的,a 是一个指向C 实例的指针,所以会调用CFunc 版本。

【讨论】:

  • 但在第二种情况下 a 的类型是 B*
  • 对于虚函数,指针的类型无关紧要。指向对象的动态类型很重要,在这两种情况下都创建一个 C。
  • @nakiya:B​​* 派生自 A。A::Func 是虚拟的,所以 B::Func 是虚拟的,C::Func 是虚拟的。
【解决方案3】:

代码不完整,添加#include和“using namespace std;”。更重要的是,您可以通过删除 A 中的虚函数声明来获得所需的行为。 一般来说,使用 CRTP 的主要原因是让模板知道它接收到的类型并避免进行虚拟调用(或者更好的是,避免将方法设为虚拟)。

template <typename T>
class ClassUsingSomething {
  public:
    void method1() {
      // I need to call method2, I do this by casting, so it doesn't need to be virtual.
      static_cast<T *>(this)->method2();
    }
};

class A: public ClassUsingSomething<A> {
  public:
    void method2() {
      //do something
    }
};

【讨论】:

    猜你喜欢
    • 2013-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多