在C ++中,是否可以使用base和派生类实现单个接口?
例如:
class Interface
{
public:
virtual void BaseFunction() = 0;
virtual void DerivedFunction() = 0;
};
class Base
{
public:
virtual void BaseFunction(){}
};
class Derived : public Base, public Interface
{
public:
void DerivedFunction(){}
};
void main()
{
Derived derived;
}
此操作失败,因为Derived无法实例化。就编译器而言,从未定义Interface :: BaseFunction。
到目前为止,我发现的唯一解决方案是在Derived中声明传递函数
class Derived : public Base, public Interface
{
public:
void DerivedFunction(){}
void BaseFunction(){ Base::BaseFunction(); }
};
有没有更好的解决方案?
编辑:如果重要,这是我使用MFC对话框时出现的现实世界问题。
我有一个从CDialog派生的对话框类(MyDialog可以说)。由于依赖性问题,我需要创建一个抽象接口(MyDialogInterface)。使用MyDialogInterface的类需要使用特定于MyDialog的方法,但还需要调用CDialog :: SetParent。我刚刚通过创建MyDialog :: SetParent并将其传递给CDialog :: SetParent来解决它,但是想知道是否有更好的方法。
答案 0 :(得分:16)
C ++没有注意到从Base继承的函数已经实现了BaseFunction
:该函数必须在从Interface
派生的类中显式实现。改变方式:
class Interface
{
public:
virtual void BaseFunction() = 0;
virtual void DerivedFunction() = 0;
};
class Base : public Interface
{
public:
virtual void BaseFunction(){}
};
class Derived : public Base
{
public:
virtual void DerivedFunction(){}
};
int main()
{
Derived derived;
}
如果您希望只能实现其中一个,请将Interface
分成两个接口:
class DerivedInterface
{
public:
virtual void DerivedFunction() = 0;
};
class BaseInterface
{
public:
virtual void BaseFunction() = 0;
};
class Base : public BaseInterface
{
public:
virtual void BaseFunction(){}
};
class Derived : public DerivedInterface
{
public:
virtual void DerivedFunction(){}
};
class Both : public DerivedInterface, public Base {
public:
virtual void DerivedFunction(){}
};
int main()
{
Derived derived;
Base base;
Both both;
}
注意:main必须返回int
注意:最好将virtual
保留在基础中虚拟的派生中的成员函数前面,即使它不是严格要求的。
答案 1 :(得分:4)
看起来Derived“is-a”Base的情况并非如此,这表明包含可能是比继承更好的实现。
此外,您的派生成员函数也应该被虚拟化为虚拟。
class Contained
{
public:
void containedFunction() {}
};
class Derived
{
public:
virtual void derivedFunction() {}
virtual void containedFunction() {return contained.containedFunction();}
private:
Containted contained;
};
如果要隐藏实现细节,可以使包含的成员成为引用或智能指针。
答案 2 :(得分:1)
问题是,在您的示例中,您有两个Interface
实现,一个来自Base
,另一个来自Derived
。这是用C ++语言设计的。正如已经指出的那样,只需删除Interface
。
Derived
基类
答案 3 :(得分:1)
我同意litb的回答。但是,这里有机会了解虚函数和多继承如何工作。
当一个类有多个基类时,它为每个基类都有单独的vtable。 Derived
将具有如下所示的vtable结构:
Derived
vtable: Interface
BaseFunction*
DerivedFunction*
vtable: Base
BaseFunction*
此外,每个基类只能看到自己的vtable。实例化Base
时,它会填充vtable中的Base::BaseFunction
指针,但无法看到接口的vtable。
如果您提供的代码可以编译,Derived
实例的结果vtable结构将如下所示:
Derived
vtable: Interface
BaseFunction* = 0
DerivedFunction* = Derived::DerivedFunction
vtable: Base
BaseFunction* = Base::BaseFunction
答案 4 :(得分:0)
我发现litb的答案中缺少一件事。如果我有Derived
个实例,我可以获得DerivedInterface
和BaseInterface
。但是,如果我只有DerivedInterface
我无法获得BaseInterface
,因为从DerivedInterface
派生BaseInterface
将无效。
但是,这一直是我一直限制自己编译时间检查的原因。这个DerivedInterface
效果很好:
class DerivedInterface
{
public:
virtual void DerivedFunction() = 0;
BaseInterface* GetBaseInterface()
{return dynamic_cast<BaseInterface*>(this);}
};
void main()
{
Derived derived;
DerivedInterface* derivedInterface = &derived;
derivedInterface->GetBaseInterface()->BaseFunction();
}
没有通过Derived中必需的功能,每个人都很高兴。当然,它不再是严格的界面了,但那没关系。我为什么不早点想到这个? :)