简体   繁体   English

从未知的派生类调用接口函数(多重继承)

[英]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 (它可以是Derived2Derived3等)。 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])在于,由于BaseInterface不相关,因此编译器必须进行盲目重新解释转换。 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 . 另一方面,编译器确实知道从BaseDerived以及从DerivedInterface 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.

相关问题 继承:从基类调用派生类函数 - Inheritance : call a derived class function from base class 从C++中具有多重继承的类派生的类:派生类试图调用根基类构造函数 - Class derived from a class with multiple inheritance in C++: the derived class is trying to call the root base class constructor 具有两个接口的多个 inheritance,一个从第一个接口派生,一个派生的 class 实现第一个接口 - Multiple inheritance with two interfaces, one which derives from first, and a derived class implementing the first interface 在多重继承中从派生类函数调用适当的父类函数 - Calling appropriate parent class function from derived class function in multiple inheritance 从具有多重继承的派生类中调用所有基类的通用命名方法 - Call a common named method of all base classes from a derived class with multiple inheritance 从基类到其他派生类的多重继承转换 - Multiple inheritance casting from base class to a different derived class 从基类到不同派生类的多重继承转换 - Multiple inheritance casting from base class to different derived class C ++继承,从基类调用派生函数 - C++ Inheritance, calling a derived function from the base class 来自派生类接口中基类的隐式特定功能 - Conceal specific function from base class in derived class interface 从基类中“导入”函数的定义以实现抽象接口(C ++中的多重继承) - “import” a definition of a function from a base class to implement abstract interface (multiple inheritance in C++)
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM