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

C++ 对象切片是否依赖于构造函数实现?,c++,polymorphism,object-slicing,C++,Polymorphism,Object Slicing,在尝试对象切片和多态性的概念时,我提出了这个代码示例,正如我所期望的那样:调用派生的functorrue类的函数调用操作符,而不是父Functor类的函数调用操作符 #include <iostream> #include <functional> using namespace std; class Functor : public std::function<bool()> { public: virtual ~Functor() {}; vir

在尝试对象切片和多态性的概念时,我提出了这个代码示例,正如我所期望的那样:调用派生的
functorrue
类的函数调用操作符,而不是父
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
}
注意:你可以

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

我的问题是:

1) 为什么构造函数中的更改会更改在
Functor>functorrue
类层次结构中调用的方法

2) 如果变体与默认构造函数所做的某些优化相关,那么该优化是什么,我如何指定它


事先非常感谢。

您有未定义的行为

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

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

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

谢谢这很可能是我第一次遇到类似的事情,或者是第一次有人指出这是问题的根本原因。未定义的行为并不是我通常将其放在脑后作为bug的可能原因。你的回答鼓励我改变这一点^^^等一下。。。
Dispatcher
类的
mFunctor
成员的常量如何不延长该
functorrue()
temporary的生命期?@levelont:临时生命期不会间接延长。从主体的角度来思考。它怎么知道(通常)构造函数将保留一个引用呢?但是。。。编译器没有执行变量生命扩展,它可以“窥视”所有代码的实现,并看到在封皮后面,有一个常量引用可以延长临时变量的生命?@levelont:没有。临时变量绑定到
functor
参数,该参数是一个引用。这会导致临时表达式一直存在到完整表达式的结束。将
函子
(它是引用,而不是临时)绑定到
mFunctor
的事实不会改变这一点。
int main() {
    Dispatcher dt = Dispatcher(FunctorTrue());
       // lifetime of FunctorTrue object ends here

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