gpt4 book ai didi

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

转载 作者:搜寻专家 更新时间:2023-10-31 02:11:49 24 4
gpt4 key购买 nike

我有 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com