假设如下:
class A{ virtual void f() = 0; };
class B{ virtual void f() = 0; };
Run Code Online (Sandbox Code Playgroud)
我能以某种方式做到以下几点吗?
class C : public A, public B
{
virtual void A::f(){ printf("f() from A"); }
virtual void B::f(){ printf("f() from B"); }
};
Run Code Online (Sandbox Code Playgroud)
所以现在我能做到???
A* pa = new C();
pa->f(); // prints f() from A;
B* pb = (B*)pa;
pb->f(); // prints f() from B;
Run Code Online (Sandbox Code Playgroud)
谢谢!!!
第一解决方案
这个问题提醒了"立面"的设计模式.这应该重写为:
class AC : public A
{ public: virtual void f(){ cout << "f() from A" << endl;}; };
class BC : public B ...
class C : public AC, public BC {};
Run Code Online (Sandbox Code Playgroud)
其中C是'立面'.
所以在正确的调用语法中应该是这样的:
C* c = new C();
c->AC::f();
c->BC::f();
Run Code Online (Sandbox Code Playgroud)
如果你在AC和BC之间没有任何共享约束,这应该可以完成工作,因为它没有被玷污.
二解决方案
另一个解决方案,感谢Casey(参见第一条评论),是在模板中使用C类的前向声明,以允许调用方法来定义后者.
template <typename C>
class AC : public A {
public:
void f() { static_cast<C&>(*this).f_from_A(); }
};
template <typename C>
class BC : public B { ... };
Run Code Online (Sandbox Code Playgroud)
所以实现部分可以在同一个类中完成.
class C : public AC<C>, public BC<C> {
public:
void f_from_A() { cout << "f_from_A" << endl; };
void f_from_B() ...
};
Run Code Online (Sandbox Code Playgroud)
调用部分更干净,因为它没有显示任何实现细节,它最接近问题:
C* c = new C();
((A*) c) -> f();
((B*) c) -> f();
Run Code Online (Sandbox Code Playgroud)
C上没有'default'f(),可以打破继承的预期行为,并且更难阅读.