我有这样的事情:
#include <iostream>
class X;
class A {
public:
virtual void bar(X &x);
};
class B : public A {
public:
};
class X {
public:
void foo(A &a) { std::cout << "foo A" << std::endl; }
void foo(B &b) { std::cout << "foo B" << std::endl; }
};
void A::bar(X &x) { x.foo(*this); }
int main(int argc, char **argv) {
X x;
B b;
b.bar(x);
return 0;
}
编译并执行它,你将得到:
# ./a.out
foo A
#
我相信这是因为对象在转换为 A 时被切片。我怎样才能避免这种情况,所以我得到
foo B
没有实现 B 中的方法或使用一些奇怪的东西,比如奇怪的重复模板模式 http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern ?
这里没有进行切片,因为您小心地通过引用传递对象;切片需要按值操作对象。
其效果是由于过载解析,这是静态完成的(即在编译时)。当C++编译这个成员函数时
void A::bar(X &x) {
x.foo(*this);
}
它需要在编译时决定选择两个重载中的哪一个。这个决定很简单:编译器知道*this
属于类型A
,所以它调用void foo(A &a)
功能。
You cannot get it to work without implementing the same method in B
*, using templates, or implementing your own dispatch scheme with function objects or lambdas.
* in which case you would end up with a nearly classic C++ implementation of the Visitor Pattern http://en.wikipedia.org/wiki/Visitor_pattern, a technique of implementing Double Dispatch http://en.wikipedia.org/wiki/Double_dispatch.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)