如何扩展继承的类的继承的类

时间:2018-08-08 16:39:18

标签: c++

假设我有这个最小的例子:

class BaseClass {
    void method1();
};

class Foo : public BaseClass {
    void method1();
};

class Bar : public Foo {
    void method1();
}

class Interface : public Foo {
};

class MyClass : public Interface, public Bar {
}

实现MyClass时,如何告诉编译器BarFoo中扩展Interface?由于转换不明确,我不断收到编译器错误。

注意:FooBar来自一个库,所以我不能仅仅为了处理这个而实现另一个接口。

1 个答案:

答案 0 :(得分:1)

class Foo
{
public:
    virtual ~Foo() { }
    virtual void f() { std::cout << "foo!" << std::endl; }
};

class Bar : public Foo
{
public:
    void f() override { std::cout << "bar!" << std::endl; }
};

现在的问题是您不能从Foo中的Interface继承: 您无法修改Bar,因此不能使其实际上继承,因此即使Interface进行了修改,您在Foo中也会得到两个MyClass的实例。因此,我的方法是在接口中引用Foo并提供明确的强制转换:

class Interface
{
    Foo& foo;
protected:
    Interface(Foo& foo) : foo(foo) { }
public:
    operator Foo&()
    {
        return foo;
    }

    virtual ~Interface() { }

    // this actually is only a short cut - you can always
    // access Foo's f via cast as well!
    // (so you can drop it, if you prefer)
    virtual void f() { foo.f(); }
};

class MyClass : public Interface, public Bar
{
public:
    MyClass() : Interface(*static_cast<Foo*>(this)) { }
    using Bar::f;
};

现在您可以按以下方式使用它:

MyClass c;
Interface* i = &c;
Foo* f = &static_cast<Foo&>(*i);
// or, if you have not yet lost access to c, simply:
f = &static_cast<Foo&>(c);

扩展:如果您需要直接实例化Interface(而不是以派生类的形式),则可以对Interface进行一些较小的修改即可实现:

class Interface
{
    Foo* foo; // raw pointer even in times of C++11 and smart pointers:
              // need to be able to delete  c o n d i t i o n a l l y
    bool isOwner;
protected:
    Interface(Foo& foo) : foo(&foo), isOwner(false) { }
public:
    Interface() : foo(new Foo()), isOwner(true) { }

    operator Foo&()
    {
        return *foo;
    }

    virtual ~Interface()
    {
        if(isOwner)
        {
            delete foo;
        }
    }

    virtual void f() { foo->f(); }
};

编辑:尽管上面的方法通常可以正常工作,但是如果您尝试通过Interface指针删除Foo(不是派生的),则会遇到麻烦。您可以通过以下方法解决该问题:

class Interface
{
    Foo& foo;
protected:
    Interface(Foo& foo) : foo(foo) { }
public:

    operator Foo&()
    {
        return foo;
    }

    virtual ~Interface() { }

    //virtual void f() { foo.f(); }
};

class MyFoo : public Interface, public Foo
{
public:
    MyFoo() : Interface(*static_cast<Foo*>(this)) { }
    virtual ~MyFoo() { }
    //using Foo::f; // don't need, if dropping the short cut
};

class MyBar : public Interface, public Bar
{
public:
    MyBar() : Interface(*static_cast<Foo*>(this)) { }
    virtual ~MyBar() { }
    //using Bar::f; // don't need, if dropping the short cut
};

现在Foo继承自BarMyBar并非继承自MyFoo,因此您无法将MyBar对象分配给MyFoo指针。但是,您都可以(通过强制转换)将一个指针分配给Foo指针,根据所讨论的问题,这是您的实际目标,所以应该没问题...