如何扩展继承类的继承类

How to extend an inherited class's inherited class

本文关键字:继承 扩展 何扩展      更新时间:2023-10-16

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

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时,如何告诉编译器Bar正在扩展Interface中的Foo?由于转换不明确,我不断收到编译器错误。

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

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; }
};

现在的问题是您无法从Interface中的Foo继承: 你不能修改Bar,因此你不能让它虚拟继承,所以即使Interface这样做了,你也会在MyClass得到两个Foo实例。所以我的方法是在接口中引用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继承自Bar,但MyBar不是从MyFoo继承的,所以你不能将MyBar对象分配给MyFoo指针。但是你们都可以(通过演员表(分配给一个Foo指针,根据讨论的问题,这是你的实际目标,所以这应该没问题......