继承:返回自我类型的函数?

问题描述:

比方说,我有两个类:继承:返回自我类型的函数?

class A 
{ 
    public: 
    A* Hello() 
    { 
     return this; 
    } 
} 

class B:public class A 
{ 
    public: 
    B* World() 
    { 
     return this; 
    } 
} 

而让我们说我有B类的一个实例,像这样:

B test; 

如果我打电话test.World()->Hello(),将工作的罚款。 但test.Hello()->World()将不起作用,因为Hello()返回A类型。

我该如何让Hello()返回B的类型?我不想使用virtual函数,因为我们有超过20个不同的类继承A

+0

20个不同的类继承A并不是那么多。你最终会得到20个vtbls,每个实例只有一个vptr(假设虚拟调度是在你的编译器上完成的)。你是如此资源受限,这真的是一个问题? – 2012-08-01 14:42:52

+1

懒惰。在类A中添加一个方法时,你必须去所有的类并添加相同的方法。 – Grapes 2012-08-01 14:47:00

您可以使用CRTP的奇异递归模板模式:

template<class Derived> 
class A 
{ 
    public: 
    Derived* Hello() 
    { 
     return static_cast<Derived*>(this); 
    } 
}; 

class B : public A<B> 
{ 
    public: 
    B* World() 
    { 
     return this; 
    } 
}; 


int main() { 
    B test; 
    test.World()->Hello(); 
    test.Hello()->World(); 
} 
+0

谢谢,这几乎完美!你仍然能够创建一个A的实例吗?我假设它看起来像这样:A 测试; – Grapes 2012-08-01 14:40:24

+0

只需要小心,因为每个从它继承的类都会得到一个单独的A类副本。如果@Grapes关心空间使用情况,这可能会比添加一个vtable更糟糕。 – Anton 2012-08-01 14:40:55

+0

您可以在B中的另一你好方法,即使它不是虚拟的:

class A 
{ 
    public: 
    A* Hello() { return this; } 
} 

class B:public class A 
{ 
    public: 
    B* Hello() { return this; } 
    B* World() { return this; } 
} 
+0

感谢Vaughn,我试图避免这种情况,因为每次在类A中添加一个新方法时,都需要遍历所有继承A的类并添加相同的方法。有没有另一种方法来做到这一点? – Grapes 2012-08-01 14:35:37

+0

@Grapes:我认为mfontanini的答案就是你要找的。 – 2012-08-01 14:37:16

+0

将不起作用,因为你不覆盖该方法,并且当你有'A'指针时'A :: Hello()'将被调用 – Andrew 2012-08-01 14:38:40

这是不必需使Hello()返回B*Hello()返回A*,您需要做的就是将您的A*转换为B*,以便能够拨打test.Hello()->World()。例如:

B* b = dynamic_cast<B*>(test.Hello()); 
if(b != 0) b->World(); 
+0

我想链我的电话就像在例子中,测试 - >你好() - >世界() - > FunctionFromA() - > FunctionFromB() - > FunctionFromA2() - > FunctionFromB(),所以我不相信这会为我工作很好。 – Grapes 2012-08-01 14:41:52