c++ - C++ 异构集合调用派生类函数

标签 c++ polymorphism

我有 A、B、C 类。 B 和 C 是从 A 派生的。B 有一个函数 foo()。 如果我创建一个 A* 数组并用 B*-s 和 C*-s 填充它,那么我无法在 B* 元素上调用 foo(),因为编译器将在 A 中搜索它。 有没有办法做到这一点,或者 A 也必须包含 foo() 函数?

最佳答案

函数 foo() 仅适用于 B 对象。这意味着您有一个指向A的指针,您无法确定该对象是否具有这样的功能。这就是编译器会提示错误的原因。

解决您问题的方法是多态性。

替代方案 1:将 A 中的函数设为虚函数

通过这种方法,您将拥有一个空的 foo() 函数,该函数对所有 AC 对象不执行任何操作,但是您会用 B 中的正确函数覆盖。

示例:

struct A {
    virtual void foo () { cout<<"nothing!"<<endl; }
};
struct B : A {
    void foo () override { cout<<"this is a B object: foo!"<<endl; }
};
struct C : A {};

int main() {
    vector<A*> va; 
    va.push_back (new A);
    va.push_back (new B); 
    va.push_back(new C); 
    for (auto x : va) 
       x->foo(); 
 }

这里是online demo

根据记录,我使用了指针 vector 而不是数组。但原理是一样的。

还请注意,经验法则是,如果类中有虚函数,则也应该有虚析构函数(为了简单起见,我在此处省略了它)。

替代方案2:使类多态并使用dynamic_cast

通过这种方法,您只需为 B 对象定义 foo() 。诀窍是,当您迭代容器时,您会检查该对象是否是 B(这要求该对象是多态的),如果是,则调用该函数。

示例:

struct A {
    virtual ~A() {};  // to make A and its descendents polymorphic, you need at least one virtual function
};
struct B : A {
    void foo () { cout<<"this is a B object: foo!"<<endl; }
};
struct C : A {};

int main() {
    vector<A*> va; 
    va.push_back (new A);
    va.push_back (new B); 
    va.push_back(new C); 
    for (auto x : va) {
        auto maybe = dynamic_cast<B*>(x);
        if (maybe) // yes, it's a B*
           maybe->foo(); 
        else cout << "still not a B"<<endl; 
    }
    return 0;
}

这里是online demo

dynamic_cast 是一种智能强制转换:如果指向的对象类型与目标类型不匹配,则 dynamic_cast 返回 nullptr .

替代方案 3:不推荐

如果 A 不能是多态的,但如果您有办法知道 A* 来确定该对象实际上是否是 B,则可以考虑最后一种选择。如果在 A 中您有一些有关对象类型的信息,则可能是这种情况。在这种情况下,您可以考虑使用 static_cast

但是不建议这样做:

  • 您必须自己管理一种方法来了解对象的类型(因此您需要手动管理,当类型是多态时编译器会自动执行的操作)。
  • 如果您在 static_cast 中犯了错误,即您认为该对象是 B 但实际上并非如此,那么您就会出现未定义的行为。

关于c++ - C++ 异构集合调用派生类函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43006122/

相关文章:

c++ - C++ 中的内存泄漏 : vector functions in loops

oop - 删除 if-is 语句的设计选择

java - 防止打印多个对象

c++ - 将工作委托(delegate)给父类(super class)的构造函数

c++ - 为什么无法从我的光照着色器访问 G-Buffer?

Android - 节奏调整?

c++ - 什么时候删除 karatsuba 算法中分配的内存?

c++ - 有人提出为什么我的代码在 basic_ios 和 sstream 中产生错误吗?

c++ - 多态性和非虚派生类方法

c++ - 如何处理类及其属性的抽象和特化?