【问题标题】:Runtime introspection in C++C++ 中的运行时自省
【发布时间】:2018-09-30 18:08:24
【问题描述】:

我有一个如下所示的课程:

class MyClass {
    public:
    void doSomething() { // nothing here };
}

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

class MyChildClass : MyClass {
    public:
    void doSomething() { // actual code here };
}

如您所见,doSomething() 函数在父类中什么也不做,但子类会覆盖它并添加实际代码。我的问题是我正在尝试做这样的事情:

MyClass foo = MyChildClass();
foo.doSomething();

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

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

【问题讨论】:

    标签: c++ class introspection object-slicing


    【解决方案1】:

    你需要两件事:

    • 指向已创建对象的引用或指针,因此它不会被复制切片。
    • 在基类中有成员函数virtual

    例如,即开即用,

    struct MyClass{ virtual void foo() {} };
    struct Derived: MyClass { void foo() override { /* ... */ } };
    
    auto main() -> int
    {
        MyClass&& o = Derived{};
        o.foo();
    }
    

    但是为什么不直接使用Derived 类型来声明呢?


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

    vector<MyClass> 将每个项目切分为 MyClass 部分。您可以使用指针向量。如果这些是拥有指针,请使用智能指针,如 shared_ptrunique_ptr

    【讨论】:

    • 谢谢!我在父文件的头文件中创建了虚拟函数,并且还直接使用了指针向量而不是对象。我不知道 std::vector 会像这样对类进行切片。我的代码现在可以正常工作了,非常感谢!
    【解决方案2】:

    如果要根据运行时信息运行函数,则需要将函数声明为虚函数。

    【讨论】:

    • 请使用 cmets 的评论部分。谢谢!
    猜你喜欢
    • 2015-03-08
    • 1970-01-01
    • 2021-12-02
    • 2011-04-21
    • 2020-01-31
    • 1970-01-01
    • 2019-02-28
    • 1970-01-01
    • 2015-11-24
    相关资源
    最近更新 更多