c++ call to base class method slices object

二次信任 提交于 2019-12-11 01:59:35

问题


I have something like this:

#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;
}

Compile it and execute it, you'll have:

# ./a.out
foo A
#

I believe this is because object is sliced when cast to A. How can I avoid this so I get

foo B

without implementing the method in B or using some weirdness like the Curiously recurring template pattern ?


回答1:


No slicing is going on here, because you carefully pass objects by reference; slicing requires manipulating the object by value.

The effect is due to overload resolution, which is done statically (i.e. at compile time). When C++ compiles this member function

void A::bar(X &x) {
    x.foo(*this);
}

it needs to decide, at compile time, which of the two overloads to pick. The decision is simple: the compiler knows that *this is of type A, so it calls void foo(A &a) function.

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, a technique of implementing Double Dispatch.



来源:https://stackoverflow.com/questions/29488392/c-call-to-base-class-method-slices-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!