我想在java或c#中使用c ++中的接口.我决定使用具有多重继承的纯抽象类,但是当我专门化接口时,有些东西是非常错误的:
class Interface
{
public:
virtual int method() = 0;
};
// Default implementation.
class Base: virtual public Interface
{
public:
virtual int method() {return 27;}
};
// specialized interface
class Interface2: public Interface
{
public:
virtual int method() = 0;
// some other methods here
};
// concrete class - not specialised - OK
class Class: public virtual Interface, public virtual Base
{
};
// concrete class - specialised
class Class2: public Interface2, public Base
{
};
int main()
{
Class c;
Class2 c2;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
警告1警告C4250:'Class':通过支配30继承'Base :: Base :: method'
错误2错误C2259:'Class2':无法实例化抽象类42
这样做的正确方法是什么?
呵呵,这个问题让我内心深处某个地方有些痒痒的。我不太清楚,但我认为这与定义接口层次结构然后继承接口和实现有关。然后,您可以通过将调用转发到基类来避免实现所有函数。我认为。
我认为这个简单的例子显示了同样的事情,但可能更容易理解一点,因为它使用了可以轻松可视化的东西:(请原谅结构懒惰)
#include <iostream>
using namespace std;
struct Vehicle
{
virtual void Drive() = 0;
};
struct VehicleImp : virtual public Vehicle
{
virtual void Drive()
{
cout << "VehicleImp::Drive\n";
}
};
struct Tank : virtual public Vehicle
{
virtual void RotateTurret() = 0;
};
struct TankImp : public Tank, public VehicleImp
{
virtual void RotateTurret()
{
cout << "TankImp::RotateTurret\n";
}
// Could override Drive if we wanted
};
int _tmain(int argc, _TCHAR* argv[])
{
TankImp myTank;
myTank.Drive(); // VehicleImp::Drive
myTank.RotateTurret(); // TankImp::RotateTurret
return 0;
}
Run Code Online (Sandbox Code Playgroud)
TankImp本质上继承了Tank接口和Vehicle实现。
现在,我很确定这是 OO 圈子里众所周知且可以接受的事情(但我不知道它是否有一个奇特的名字),所以在这种情况下可怕的钻石事情是可以的,你可以安全地抑制支配警告,因为在这种情况下这是你想要发生的。
希望能以某种方式帮助您指明正确的方向!
顺便说一句,您的代码无法编译,因为您没有在 Class2 中实现纯虚拟“方法”。
编辑:
好吧,我想我现在更好地理解你的问题了,我认为错误出在 Interface2 中。尝试将其更改为这样:
// specialized interface
class Interface2: public virtual Interface // ADDED VIRTUAL
{
public:
//virtual int method() = 0; COMMENTED THIS OUT
// some other methods here
};
Run Code Online (Sandbox Code Playgroud)
Interface2 不应该具有方法的纯虚拟定义,因为它已经在 Interface 中了。
Interface 的继承必须是虚拟的,否则当您从 Class2 中的 Interface2 和 Base 派生时,您将与 Base::method 产生歧义。
现在你应该发现它可以编译,可能会出现支配警告,当你调用 c2.method() 时,你会得到 27。