通过继承实现纯虚函数

时间:2013-04-19 17:07:17

标签: c++ inheritance virtual

我有以下情况:

class Fork {
    public:
        virtual void use() = 0;
};

class Spoon {
    public:
        virtual void use() = 0;
};

class SilverSpoon : public Spoon {
    public:
        virtual void use() { }
};

class SilverSpork : public SilverSpoon, public Fork {
    public:
        using SilverSpoon::use;
};

我希望Fork::use中的SilverSpoon::use定义纯虚函数SilverSpork。但是,我得到了

error: cannot declare variable ‘spork’ to be of abstract type ‘SilverSpork’
note:  because the following virtual functions are pure within ‘SilverSpork’:
note:  virtual void Fork::use()

有没有办法解决这个问题而无需添加

virtual void use() {
    SilverSpoon::use();
}

SilverSpork

3 个答案:

答案 0 :(得分:4)

ForkSpoon之间没有固有的联系,而且它们都有一个名为use的虚函数这一事实并没有成功。但是,如果您添加一个新类,比如Utensil定义一个纯虚函数use(),并从中导出ForkSpoon作为虚拟基础,那么有联系。这样,班级SilverSpork 选择SilverSpoon::use的实施作为其直接基地useFork的替代者。这被称为“支配地位”。

class Utensil {
public:
    virtual void use() = 0;
};

class Spoon : public virtual Utensil {
public:
    virtual void use() = 0; // or can omit this, relying on Utensil
};

class Fork : public virtual Utensil {
public:
    virtual void use() = 0; // or can omit this, relying on Utensil
};

class SilverSpoon : public Spoon {
public:
    void use() { }
};

class SilverSpork : public SilverSpoon, public Fork {
}; // OK: SilverSpoon::use overrides Fork::use

答案 1 :(得分:2)

Fork::use()Spoon::use()是两种具有相同名称的不同方法,可扩展为SilverSpork

编译器希望它们都能实现。它只是一个冲突而不是覆盖或超载的名称。可能性是从基础虚拟类继承Fork和Spoon:

class Object {
    public:
        virtual void use() = 0;    
};

class Fork : virtual public Object {
};

class Spoon: virtual public Object {
};

class SilverSpoon : public Spoon {
    public:
        virtual void use() { cout << "SilverSpoon" << endl; }
};

class SilverSpork : public SilverSpoon, public Fork {
    public:
        using SilverSpoon::use;
};

图:

                                    +---------------+
                                    |    Object     |
                                    +---------------+
                                      ^           ^
                                      |           |
                                      |           |
                                      |           |
                       +---------------+         +---------------+
                       |    Spoon      |         |     Fork      |
                       +---------------+         +---------------+
                               ^                  ^
                               |                  |
                               |                  |
                               |                  |
                       +---------------+          |
                       |  SilverSpoon  |          |
                       +---------------+          |
                                      ^           |
                                      |           |
                                      |           |
                                      |           |
                                   +---------------+
                                   |  SilverSpork  |
                                   +---------------+

答案 2 :(得分:2)

由于您使用多重继承,因此您实际上继承了两种不同的抽象use方法,并且必须在您的孩子中覆盖两者

您需要问自己的第一个问题是SilverSporkuse具有相同SilverSpoon行为的原因。如果确实如此,我无法相信我会建议这样做,但你可以通过使用钻石继承和新的虚拟基础来解决这个问题:

class Utinsil
{
    public:
        virtual void use() = 0;
};

class Fork : public virtual Utinsil {
};

class Spoon : public virtual Utinsil {
};

class SilverSpoon : public Spoon {
    public:
        virtual void use() { }
};

class SilverSpork : public SilverSpoon, public Fork {
};

int main()
{
    SilverSpork silver_spork;
}