2010-02-24 85 views
1

我有这3个类。继承与CRTP

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

而且它打印: “在C”。

如果我这样做,

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

    return 0; 
} 
再次

它打印 “在C”

这是怎么回事?

+1

不可读的代码。 – Drakosha 2010-02-24 10:41:00

+1

你会期望它打印什么呢? – sth 2010-02-24 10:41:53

+0

在第二种情况下“在B中”,然后是“在C中”? – nakiya 2010-02-24 10:53:11

回答

1

你叫谁重载了这个功能的C类对象的虚成员函数。它要求在C类功能

此外,这不是CRTP作为模板类B没有从类模板参数继承。

+0

原代码(你之前修复)缺少了不少必要的东西,所以这是很难说有什么最初的意思。也许CRTP的东西也不小心丢失了...... – user64075 2010-02-24 10:51:56

+0

你是什么意思,这不是CRTP?你的意思是B应该继承C吗? – nakiya 2010-02-24 10:54:09

+0

号CRPT意味着乙应从T. – 2010-02-24 12:12:49

1

Func是虚拟的,a是指向的C一个实例,因此C的版本的Func被调用。

+0

继承但在第二情况下的是B型的 nakiya 2010-02-24 11:01:44

+1

*随着虚拟函数的指针的类型并不重要。指向对象的动态类型很重要,并且在这两种情况下都会创建一个C. – UncleBens 2010-02-24 11:18:15

+0

@nakiya:B​​ *源自A. A :: Func是虚拟的,所以B :: Func是虚拟的而C :: Func是虚拟的。 – 2010-02-24 11:53:49

0

的代码是不完整的,添加#和“使用命名空间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 
    } 
}; 
+0

另见: http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern – Blaisorblade 2010-05-05 17:01:31