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

时间:2017-05-16 12:15:35

标签: c++ polymorphism object-slicing

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

#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方法只知道&#34; base课程部分&#34;该对象,有效地调用基类的函数调用操作符。但是在原始例子中并不成立,这让我感到困惑。

我的问题是:

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

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

提前多多感谢。

1 个答案:

答案 0 :(得分:4)

您有未定义的行为。

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

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

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