用基类和派生类移动作业

时间:2018-11-07 16:13:23

标签: c++

下面是我遇到的两个类的缩小实现。

代码:

这是基类:

//header
class Script
{
public: 
    Script(const QString& path, int timeout=10000) : 
    mPath(path), mTimeout(timeout), script(new QProcess) {}
    Script(Script&& s);
    Script& operator=(Script&& s);
    virtual ~Script();

protected:
    QString mPath;
    int mTimeout;
    QProcess* script;
}

//source
Script::Script(Script&& s) :
    mPath(s.mPath), mTimeout(s.Timeout), script(s.script)
{
    s.script = nullptr;
}

Script& Script::operator=(Script&& s){
    if(&s != this){
        delete script;
        script = s.script;
        s.script = nullptr;

        mPath = s.mPath;
        mTimeout = s.mTimeout;
    }
    return *this;
}

Script::~Script() {
    delete script;
    script = nullptr;
}

从上面的代码片段中,我得出以下类:

//header
class ConfigurationScript : public Script
{
public:
    ConfigurationScript(const QString& path);
    ConfigurationScript(ConfigurationScript&& s);
    ConfigurationScript& operator=(ConfigurationScript&& s);
}

//source
ConfigurationScript::ConfigurationScript(const QString& path) :
Script(path) {}

ConfigurationScript::ConfigurationScript(ConfigurationScript&& s) : 
Script(std::move(s)) {}

ConfiguratonScript& ConfigurationScript::operator=(ConfigurationScript&& s) {
    if(&s != this){
        delete script;
        script = s.script;
        s.script = nullptr;

        mPath = s.mPath;
        mTimeout = s.mTimeout;
    }
    return *this;
}

问题:

ConfigurationScript的移动分配与其基类Script的移动分配进行比较时,它包含重复的代码。您可以调用基类的赋值运算符来克服重复的代码吗?

例如这样有效吗?

ConfigurationScript& ConfigurationScript::operator=(ConfigurationScript&& s) {
    if(&s != this){
        Script::operator=(s);
    }
    return *this;
}

Script::operator=(s)的返回类型为Script,是否需要将其强制转换为ConfigurationScript? 如果以上方法有效,我将看不到它的工作原理。否则,有没有办法避免代码重复?

1 个答案:

答案 0 :(得分:2)

是的,这是有效的,而且您无需投放任何内容。

您甚至没有使用基本的op=调用的结果,但是您知道它是一个Script&引用当前对象。由于您已经有一个指向当前对象ConfigurationScript&,并且具有所需的类型(即*this),因此无需执行其他操作。

实际上,这很自然,您可以让编译器为您完成:

#include <iostream>
#include <utility>

struct Base
{
    Base& operator=(Base&& other)
    {
        std::cout << "YOLO!\n";
        return *this;
    }
};

struct Derived : Base
{
    /*
    // Don't need this
    Derived& operator=(Derived&& other)
    {
        Base::operator=(std::move(other));
        return *this;
    }*/

    /*
    // Or even this (though you may need to introduce it
    // if you have some other user-declared stuff)
    Derived& operator=(Derived&& other) = default;
    */
};

int main()
{
    Derived d1, d2;
    d2 = std::move(d1);
}

// Output: YOLO!

live demo

但是我认为您可能是想Script::operator=(std::move(s))才能获得真正的发展,而不是复制。