C++中的运行时内省

Chr*_*ley 1 c++ class introspection object-slicing

我有一个看起来像这样的课程:

class MyClass {
    public:
    void doSomething() { // nothing here };
}
Run Code Online (Sandbox Code Playgroud)

它还有一个看起来像这样的子类

class MyChildClass : MyClass {
    public:
    void doSomething() { // actual code here };
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,该doSomething()函数在父类中不执行任何操作,但子类会覆盖它并添加实际代码.我的问题是我试图做这样的事情:

MyClass foo = MyChildClass();
foo.doSomething();
Run Code Online (Sandbox Code Playgroud)

我很震惊地发现,在这种情况下,MyClass而不是MyChildClass的版本doSomething()被称为,即使FOO实际类型为MyChildClass.我在Objective-C方面的经验远远超过C++,所以这对我来说非常奇怪.似乎C++正在确定doSomething()在编译时需要调用哪个版本的版本,而不是在运行时检查对象的类型并调用正确的版本.

这对我来说是有问题的,因为在我的实际代码中,我拥有的是一个父类和从中继承的多个不同的子类.这些子类中的每一个都doSomething()使用它们自己的唯一实现来覆盖该函数.我最终拥有一个std::vector完整的MyClass对象(它们实际上充满了各自继承的许多不同类型的对象MyClass),我想循环遍历这些对象并调用它们的版本,doSomething()而不是在编译时实际知道它们的类型.在Objective-C中这很容易,但是我有什么方法可以在C++中实现这一点吗?

Che*_*Alf 5

你需要两件事:

  • 指向已创建对象的引用或指针,以便它不会被复制切片.
  • virtual基类中具有成员函数.

例如,脱下袖口,

struct MyClass{ virtual void foo() {} };
struct Derived: MyClass { void foo() override { /* ... */ } };

auto main() -> int
{
    MyClass&& o = Derived{};
    o.foo();
}
Run Code Online (Sandbox Code Playgroud)

但为什么不只是使用Derived声明的类型?


"我最终得到了一个充满MyClass对象的std :: vector(它实际上充满了许多不同类型的对象,每个对象都继承自MyClass),我想循环遍历每个对象并调用它们的doSomething()版本而不用实际上在编译时知道它们的类型.

vector<MyClass>每个项目切片到MyClass零件.您可以使用指针向量.如果这些是拥有指针,请使用像shared_ptr或的智能指针unique_ptr.