问题描述
我早些时候问了一个问题,但事实证明我的问题没有通过我的示例正确建模.所以这是我的实际问题:
I asked a question earlier but it turns out my problem was not properly modeled by my example. So here is my actual problem:
- 我有类
A
,类B
继承自A
, - 我有两个函数
foo(A&)
和foo(B&)
, - 我有一个
A*
指针列表,其中包含A
和B
的实例. - 如何为
A
的实例调用foo(A&)
为的实例调用
foo(B&)
>B代码>?约束:我可以修改A
和B
的实现,但不能修改foo
的实现.
- I have class
A
, and classB
inheriting fromA
, - I have two functions
foo(A&)
andfoo(B&)
, - I have a list of
A*
pointers, containing instances ofA
andB
. - How do I get to call
foo(A&)
for instances ofA
andfoo(B&)
for instances ofB
? Constraints: I can modifyA
andB
implementation, but notfoo
's implementation.
看下面的例子:
#include <iostream>
#include <list>
class A {
public:
};
class B : public A {
public:
};
void bar(A &a) { std::cout << "This is an A" << std::endl; }
void bar(B &b) { std::cout << "This is a B" << std::endl; }
int main(int argc, char **argv) {
std::list<A *> l;
l.push_back(new B());
l.push_back(new B());
for (std::list<A *>::iterator it = l.begin(); it != l.end(); ++it)
bar(**it);
}
虽然我使用的是带有指针的容器,但 bar
是用父类中的对象调用的,而不是子类:
Although I am using a container with pointers, bar
is called with object from the parent class, not the child class:
# ./a.out
This is an A
This is an A
#
我期待
This is a B
将指针传递给 bar
(通过重写其签名)没有帮助.
Passing pointers to bar
(by rewriting its signature) does not help.
感谢 Antonio 帮助澄清问题.
Thx to Antonio for helping clarifying the question.
推荐答案
由于重载是在编译时解决的,你需要为编译器提供足够的信息来决定 bar
的正确重载称呼.由于您希望根据对象的运行时类型动态地做出决定,因此虚函数会很有帮助:
Since overloading is resolved at compile time, you need to supply the compiler with enough information to decide on the proper overload of bar
to call. Since you wish to make that decision dynamically based on the run-time type of the object, virtual functions would be of great help:
struct A {
virtual void bar() { bar(*this); }
};
struct B : public A {
virtual void bar() { bar(*this); }
};
可能看起来身体是相同的,所以 B::bar
可以被消除,但事实并非如此:虽然身体看起来完全一样,但它们调用不同的 bar
s 由于 C++ 中重载的静态解析:
It may seem like the bodies are identical, so B::bar
could be eliminated, but this is not true: although the bodies look exactly the same, they call different bar
s due to the static resolution of overloads in C++:
A::bar
内部*this
的类型是A&
,所以调用了第一个重载.B::bar
内部*this
的类型是B&
,所以调用了第二个重载.
- Inside
A::bar
the type of*this
isA&
, so the first overload is called. - Inside
B::bar
the type of*this
isB&
, so the second overload is called.
修改调用代码调用成员bar
即可完成更改:
Modify the calling code to call the member bar
will complete the change:
std::list<A *> l;
l.push_back(new B());
l.push_back(new B());
for (std::list<A *>::iterator it = l.begin(); it != l.end(); ++it)
(*it)->bar();
这篇关于对于重载函数,调用父子实例的专用版本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!