关于转换:C ++转换为基类

C++ cast to base class

本问题已经有最佳答案,请猛点这里访问。

我有一个基类A和一个派生类B

1
2
3
4
5
6
7
8
9
10
11
12
class A {
public:
    int x;
    virtual int getX() {
        return x;
    }
};

class B : public A {
public:
    int y;
};

虚拟函数的存在只是为了使其具有多态性。接下来,我宣布一份A的清单,但把B放在里面:

1
2
3
4
5
6
7
vector<A> list;
B b1,b2;
b1.y = 2;
b2.x = 10;

list.push_back(b1);
list.push_back(b2);

现在,我要检查向量上的所有元素,并访问y成员(只有B有):

1
2
3
4
5
for (auto it = list.begin(); it != list.end(); ++it) {
    B &cast = dynamic_cast<B&>(*it);
    int value = cast.y;
    std::cout << value << std::endl;
}

此代码提供运行时错误。你知道我该怎么做演员表和访问y吗?


正在发生的是一个对象切片。

实现目标的一种方法是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <vector>
#include <iostream>

using namespace std;

class A {
  public:
    int x;
    virtual int getX() {
      return x;
    }

    virtual ~A() = default;
};

class B : public A {
  public:
    int y;
};

int main() {
  vector<A*> list;
  B b1,b2;
  b1.y = 2;
  b2.x = 10;

  list.push_back(&b1);
  list.push_back(&b2);

  for (auto it = list.begin(); it != list.end(); ++it) {
    B* cast = dynamic_cast<B*>(*it);
    int value = cast->y;
    std::cout << value << std::endl;
  }

  return 0;
}

在这个示例代码中,我们使用指针来避免对象切片。如cdhowie所述:运行时多态性需要使用指针或引用

另一件重要的事情:在创建类层次结构时,始终使基类析构函数为虚拟的,否则会出现内存问题。