c++ - 对象切片是否依赖于构造函数的实现?

标签 c++ polymorphism object-slicing

在尝试对象切片和多态性的概念时,我想出了这个代码示例,它按我的预期工作:派生 FunctorTrue 的函数调用运算符类被称为 - 而不是父类 Functor类。

#include <iostream>
#include <functional>
using namespace std;

class Functor : public std::function<bool()> {
public:
virtual ~Functor() {};
    virtual bool operator()() const {return false;};
};

class FunctorTrue : public Functor{
public:
    bool operator()() const {return true;}
};

class Dispatcher {
public:
    const Functor & mFunctor; 
    Dispatcher(const Functor & functor): mFunctor(functor) {}
    Dispatcher(const Functor && functor): mFunctor(functor) {
    }

    void dispatch(){
        cout << boolalpha << mFunctor() << endl;
    }
};

int main() {
    Dispatcher dt = Dispatcher(FunctorTrue());
    dt.dispatch(); // returns true
}

注意:您可以run this example in Ideone .

我发现如果我修改 Dispatcher 的构造函数类打印一行,父级的函数调用运算符将​​被调用:

class Dispatcher {
public:
    const Functor & mFunctor; 
    Dispatcher(const Functor & functor): mFunctor(functor) {}
    Dispatcher(const Functor && functor): mFunctor(functor) {
        cout << "Constructor with rvalue" << endl;
    }

    void dispatch(){
        cout << boolalpha << mFunctor() << endl;
    }
};

int main() {
    Dispatcher dt = Dispatcher(FunctorTrue());
    dt.dispatch(); // returns false
}

注意:您可以also run this example in Ideone

这种意外的行为让我认为,由于成员变量 mFunctor 的类型在 Dispatcher类,dispatch方法只知道对象的“基类部分”,有效地调用基类的函数调用运算符。但这在最初的例子中并不成立,这让我很困惑。

我的问题是:

1) 为什么构造函数中的更改会更改 Functor > FunctorTrue 中调用的方法类(Class)层次?

2) 如果变化与默认构造函数执行的某些优化相关,那么该优化是什么以及如何指定它?

提前非常感谢。

最佳答案

您有未定义的行为。

您的构造函数存储对生命周期结束的对象的引用,然后 dispatch() 尝试使用该对象。

int main() {
    Dispatcher dt = Dispatcher(FunctorTrue());
       // lifetime of FunctorTrue object ends here

    dt.dispatch(); // Use of dt.mFunctor causes undefined behavior
}

关于c++ - 对象切片是否依赖于构造函数的实现?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44001189/

相关文章:

c++ - 谷歌测试/模拟 Qt 信号

oop - 删除 if-is 语句的设计选择

java - 为什么 Java API 中的许多方法都有 "abstract"修饰符?

c++ - 基指针 C++ 派生类的类型

c++ - 调用虚拟方法而不是派生方法

c++ - 节点* temp之间的差异;和节点* tmp =新节点;

c++ - "const std::stop_token&"或者只是 "std::stop_token"作为线程函数的参数?

c++ - C代码意外成功

c++ - 什么是对象切片?

c++ - 将函数对象分配给函数包装器后出现意外行为