C++调用基类方法切片对象

标签 c++ polymorphism overloading object-slicing

我有这样的东西:

#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 中的方法或使用一些奇怪的东西,比如 Curiously recurring template pattern

最佳答案

这里没有进行切片,因为您小心地通过引用传递对象;切片需要按值操作对象。

该效果是由于重载解析所致,该解析是静态完成的(即在编译时)。当C++编译这个成员函数时

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

它需要在编译时决定选择两个重载中的哪一个。这个决定很简单:编译器知道 *this类型为A ,所以它调用 void foo(A &a)功能。

如果不在 B 中实现相同的方法,就无法让它工作。 *,使用模板,或使用函数对象或 lambda 实现您自己的调度方案。

* 在这种情况下,您最终会得到 Visitor Pattern 的近乎经典的 C++ 实现。 ,一种实现 Double Dispatch 的技术.

关于C++调用基类方法切片对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29488392/

相关文章:

c++ - 无法初始化指向具有基类右值的子类的指针

C++:如何解决具有多个多态输入的方法调用?

c++ - 在 C++ 中声明没有隐式转换的类型

c++ - 安全销毁包含 shared_ptr 的映射

c++ - 如何注入(inject)模拟对象?

c++ - 继承:动态派生类成员与静态派生类成员

Java 重载对象

android - 在 Android 上重载静态字段

c# - 使用相同的参数签名重载

c++ - 如何在一个列表中存储不同的数据类型? (C++)