[英]Call an interface function from an unknown derived class (multiple inheritance)
I have an array of Base*
objects. 我有一个
Base*
对象数组。 This holds a bunch of derived objects, some of which may implement an Interface
. 它包含一堆派生对象,其中一些可以实现
Interface
。
struct Base {
virtual void doNotCallThis() { cout << "nooo" << endl; }
};
struct Interface {
virtual void doThis() = 0;
};
// Example derived class
struct Derived : Base, virtual Interface {
virtual void doThis() { cout << "yes" << endl; }
};
int main() {
Base* b[1];
b[0] = new Derived(); // Here would be a bunch of different derived classes
((Interface*)b[0])->doThis(); // Elsewhere, doThis() would be called for select array elements
return 0;
}
Output: 输出:
nooo
I don't know the exact type of b[i]
at run time, so I can't cast to Derived
(it could be Derived2
, Derived3
, etc). 我在运行时不知道
b[i]
的确切类型,所以我不能转换为Derived
(它可以是Derived2
, Derived3
等)。 I also can't use dynamic_cast if that's a solution. 如果这是解决方案,我也无法使用dynamic_cast。 All I know is that, by the time I call
doThis()
, b[i]
is a type that inherits from Interface
. 我所知道的是,当我调用
doThis()
, b[i]
是从Interface
继承的类型。 The way I attempted to call it above causes the wrong function to be called, eg. 我在上面尝试调用它的方式导致错误的函数被调用,例如。
Base::doNotCallThis()
. Base::doNotCallThis()
。
How can I call it properly? 我怎么称呼它?
As other people have pointed out, you would probably do best to find a way to refactor your design so that casting isn't necessary. 正如其他人指出的那样,您可能会最好地找到一种方法来重构您的设计,从而不必进行强制转换。
But putting that aside, I can explain what's going wrong and how to correctly cast. 但是抛开这些,我可以解释出了什么问题以及如何正确进行转换。
The problem with ((Interface*)b[0])
is that since Base
and Interface
are unrelated the compiler has to do a blind reinterpretive cast. ((Interface*)b[0])
在于,由于Base
和Interface
不相关,因此编译器必须进行盲目重新解释转换。 Practically speaking that means in this situation the resulting pointer doesn't actually line up with the Interface
part of the object. 实际上,这意味着在这种情况下,所得的指针实际上未与对象的
Interface
部分对齐。 If you were to try static_cast<Interface*>(b[0])
you would find it doesn't compile - and that's a big hint that it's the wrong kind of cast to be making. 如果您尝试使用
static_cast<Interface*>(b[0])
您会发现它无法编译-这是一个很大的暗示,表明它是一种错误的类型。
On the other hand, the compiler does know the relationship from Base
to Derived
and also from Derived
to Interface
. 另一方面,编译器确实知道从
Base
到Derived
以及从Derived
到Interface
。 So as long as you know for sure that the object not only implements Interface
but also is a Derived
then you can do: 因此,只要您确定对象不仅实现了
Interface
而且还实现了Derived
那么您可以执行以下操作:
static_cast<Interface*>(static_cast<Derived*>(b[0]))->doThis();
However if your design has multiple different derived types which independently implement Interface
then you might not be able to do that unless again you absolutely know what the derived type is at any time you go to make the call. 但是,如果您的设计有多个不同的派生类型,这些派生类型独立地实现
Interface
那么您可能无法做到这一点,除非您再次完全知道派生类型是什么,然后再进行调用。 - This is why refactoring it into a better class hierarchy is more desirable, since it's much less fragile and cumbersome to work with. -这就是为什么更需要将其重构为更好的类层次结构,因为使用它的脆弱性和麻烦性要小得多。
(As a side note, this issue points out why it's a great idea to never use raw/reintrepretive casts when moving up and down a class hierarchy. At least use static_cast
since the can compiler better help you do it correctly.) (作为附带说明,此问题指出了为什么在上下移动类层次结构时永远不使用原始/隐式强制转换是一个好主意。至少可以使用
static_cast
因为can编译器可以更好地帮助您正确地进行操作。)
Writing an answer with the risk of being downvoted: 写一个有被低估的风险的答案:
If we start with:: 如果我们以:
struct Base()
{
virtual void SomeFunc();
};
struct Interface
{
virtual void doThis();
}
then to create a bunch of derived functions from Base that are also interfaces, I'd do something like this: 然后要从Base导出一堆也是接口的派生函数,我需要执行以下操作:
struct BaseInterface : public Base, public Interface
{
// Nothing here - this is just combining Base and Interface
};
struct Base1 : public BaseInterface
{
... add stuff that Base1 has that isn't in Base.
};
struct Derived: public Base1
{
... some more stuff that isn't in Base1
}
And then we use it in Main like this: 然后像这样在Main中使用它:
int main() {
BaseInterface* b[1];
b[0] = new Derived(); // Here would be a bunch of different derived classes
b[0])->doThis(); // Elsewhere, doThis() would be called for select array elements
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.