我有A,B,C班。 B和C源自A.B具有函数foo()。 如果我创建一个A *数组并用B * -s和C * -s填充它,那么我就不能在B *元素上调用foo()因为编译器将在A中搜索它。 有没有办法,或者A必须包含foo()函数?
答案 0 :(得分:2)
函数foo()
仅为B
个对象所知。这意味着你有一个指向A
的指针,你无法确定该对象是否具有这样的功能。这就是编译器会抱怨错误的原因。
您的问题的解决方案是多态性。
使用这种方法,您有一个空的foo()
函数,它不会对所有A
和C
个对象执行任何操作,但您可以使用正确的函数覆盖在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
对于记录,我使用指针向量而不是数组。但原则是一样的。
另请注意,经验法则是,如果类中有虚函数,则还应该有一个虚拟析构函数(为简单起见,我在此省略)。
使用此方法,您只能为foo()
对象定义B
。诀窍是当您遍历容器时,检查对象是否为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
。
如果A不能是多态的,那么可以考虑最后一个替代方案,但是如果你知道一个A *来确定该对象是否是一个B或者不是。这可能是这种情况,如果在A中你有关于对象类型的一些信息。在这种情况下,您可以考虑static_cast
。
但不建议这样做:
static_cast
中犯了错误,即您认为该对象是B,但实际上并非如此,那么您将有一个未定义的行为。