假设我有这个最小的例子:
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
在Foo
中扩展Interface
?由于转换不明确,我不断收到编译器错误。
注意:Foo
和Bar
来自一个库,所以我不能仅仅为了处理这个而实现另一个接口。
答案 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
继承自Bar
,MyBar
并非继承自MyFoo
,因此您无法将MyBar
对象分配给MyFoo
指针。但是,您都可以(通过强制转换)将一个指针分配给Foo
指针,根据所讨论的问题,这是您的实际目标,所以应该没问题...