三/五规则适用于继承和虚拟析构函数吗? [英] Does rule of three/five apply to inheritance and virtual destructors?

查看:243
本文介绍了三/五规则适用于继承和虚拟析构函数吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

让我们假设我们有一个非常基本的 A类

  class A {
public:
void SetName(const std :: string& newName){
m_name = newName;
}

void Print()const {
std :: printf(A :: Print()。Name:%s\\\
,m_name.c_str );
}
private:
std :: string m_name;
};

我们想用 class B 因此我们添加虚拟析构函数,将一个成员更改为 virtual 并将 private 更改为 protected for inh:

  A类{
public:
virtual〜A (){}

void SetName(const std :: string& newName){
m_name = newName;
}

virtual void Print()const {
std :: printf(A :: Print()。Name:%s\\\
,m_name.c_str ));
}
protected:
std :: string m_name;

};

class B:public A {
public:
virtual void Print()const {
std :: printf( %s\\\
,m_name.c_str());
}
};

现在,因为我们在 A类中添加了析构函数我们需要创建一个复制构造函数和复制运算符吗?

  class A {
public:
virtual〜A(){}

A()= default;
A(const A©From){
* this = copyFrom;
}
virtual A& operator =(const A& copyFrom){
m_name = copyFrom.m_name;
return * this;
};

void SetName(const std :: string& newName){
m_name = newName;
}

virtual void Print()const {
std :: printf(A :: Print()。Name:%s\\\
,m_name.c_str ));
}
protected:
std :: string m_name;

};

对我来说,这似乎是不必要的,因为默认的复制操作符和复制构造函数会做同样的事情。为了为语言的潜在未来演变做好准备,你应该明确默认复制/移动构造函数和赋值运算符,当你添加虚拟析构函数。这是因为当类有一个用户声明的析构函数时,C ++ 11,12.8 / 7隐式生成拷贝构造函数。



幸运的是,C ++ 11的显式默认使其定义容易:

  class A {
public:
virtual〜A(){}

A()= default;
A(const A& copyFrom)= default;
A& operator =(const A& copyFrom)= default;
A(A&&)= default;
A& operator =(A&&)= default;

void SetName(const std :: string& newName){
m_name = newName;
}

virtual void Print()const {
std :: printf(A :: Print()。Name:%s\\\
,m_name.c_str ));
}
protected:
std :: string m_name;

};


Let's assume we have a very basic class A:

class A {
    public:
        void SetName(const std::string& newName) {
            m_name=newName;
        }

        void Print() const {
            std::printf("A::Print(). Name: %s\n",m_name.c_str());
        }
    private:
        std::string m_name;  
};

We want to extend this class with class B so we add our virtual destructor, change a member to virtual and change private to protected for inh:

class A {
    public:
        virtual ~A() {}

        void SetName(const std::string& newName) {
            m_name=newName;
        }

        virtual void Print() const {
            std::printf("A::Print(). Name: %s\n",m_name.c_str());
        }
    protected:
        std::string m_name;

};

class B : public A {
    public:
        virtual void Print() const {
            std::printf("B::Print(). Name: %s\n",m_name.c_str());
        }
};

Now since we added a destructor in class A do we need to create a copy constructor and copy operator like so?

class A {
    public:
        virtual ~A() {}

        A() = default;
        A(const A& copyFrom){
            *this = copyFrom;
        }
        virtual A& operator=(const A& copyFrom){
            m_name=copyFrom.m_name;
            return *this;
        };

        void SetName(const std::string& newName) {
            m_name=newName;
        }

        virtual void Print() const {
            std::printf("A::Print(). Name: %s\n",m_name.c_str());
        }
    protected:
        std::string m_name;

};

To me this seems unnecessary as the default copy operator and copy constructor would do the same thing.

解决方案

To be prepared for potential future evolution of the language, you should indeed explicitly default the copy/move constructors and assignment operators when you add a virtual destructor. That's because C++11, 12.8/7 makes implicit generation of copy constructors deprecated when the class has a user-declared destructor.

Fortunately, C++11's explicit defaulting makes their definition easy:

class A {
    public:
        virtual ~A() {}

        A() = default;
        A(const A& copyFrom) = default;
        A& operator=(const A& copyFrom) = default;
        A(A &&) = default;
        A& operator=(A &&) = default;

        void SetName(const std::string& newName) {
            m_name=newName;
        }

        virtual void Print() const {
            std::printf("A::Print(). Name: %s\n",m_name.c_str());
        }
    protected:
        std::string m_name;

};

这篇关于三/五规则适用于继承和虚拟析构函数吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆