C ++:Derived + Base类实现单个接口?

时间:2008-11-14 18:11:07

标签: c++ class inheritance interface

在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来解决它,但是想知道是否有更好的方法。

5 个答案:

答案 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个实例,我可以获得DerivedInterfaceBaseInterface。但是,如果我只有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中必需的功能,每个人都很高兴。当然,它不再是严格的界面了,但那没关系。我为什么不早点想到这个? :)