用继承和虚函数应用五规则

时间:2018-03-27 16:00:20

标签: c++ c++11 c++14

我见过的每个实现五条规则的例子都在没有继承和多态(虚函数)的类上实现规则。

如何将5的规则应用于示例代码?

测试示例使用c-arrays作为动态对象。 当然,为了让动态对象能够管理以演示五级规则,这有点做作。实际上,它可能是任何东西(文件ptrs,数据库句柄等)。因此,不建议使用向量,或将练习转化为零规则的演示。

我更倾向于不使用复制交换习惯用法的解决方案,因为在非继承类的情况下,我发现非复制交换方法更明确。但是,如果有人希望说明这两种方法,那也会很棒。

关于示例代码的说明:

  • B继承自A.
  • A& A& B有自己的动态对象来管理(一个人为的c阵列)。
  • T类是一个设计类,用于诊断打印的自定义类型。 c-arrays存储T元素。
  • A类& B没有五条规则的实施(由答案定义)
  • 尚未在示例代码中分配c数组,但当然,它们将基于各自的bufferSize进行构建。

示例代码

//TEST TYPE
class T
{
public:
        T()  { cout << "ctorT" << endl; }
        ~T() { cout << "dtorT" < endl; }

        T(const T& src)             { cout << "copy-ctorT  " << endl; }
        T& operator=(const T& rhs)  { cout << "copy-assignT" << endl; return *this; }
        T(T&& src) noexcept         { cout << "move-ctorT  " << endl; }
        T& operator=(T&& rhs)       { cout << "move-assignT" << endl; return *this; }
}

class A
{
    string nameParent = "A";
    size_t bufferSizeParent = 0;
    T *pBufferParent = nullptr;                 //c-array

public:
    A(string tNameParent, size_t tBufferSizeParent) : nameParent(tNameParent), bufferSizeParent(tBufferSizeParent)
    {
        cout << "ctorA " << nameParent << endl;
    }

    virtual ~A(){ cout << "dtorA " << nameParent << endl; }     
    virtual string getName()                    { return nameParent; }
    virtual void setName(const string name)     { nameParent = name; }
};

class B : public A
{
    string nameChild = "B";
    size_t bufferSizeChild = 0;
    T *pBufferChild = nullptr;              //c-array

public:
    B(string tNameChild, string tNameParent, size_t tBufferSizeChild, size_t tBufferSizeParent) 
    : A(tNameParent, tBufferSizeParent), nameChild(tNameChild), bufferSizeChild(tBufferSizeChild)
    {
        cout << "ctorB " << nameChild << endl;
    }

    ~B(){ cout << "dtorB " << nameChild << endl; }             

    virtual string getName() override final             { return nameChild; }
    virtual void setName(const string name) override final  { nameChild = name; }
};

1 个答案:

答案 0 :(得分:0)

一个好的经验法则是,一个班级应该直接管理最多一个资源。其他类具有所有default个特殊成员,最好是隐式的,但如果要在某些变体中声明它们,则应明确。

您的示例变为

struct T;
extern T acquire_T();
extern void release_T(T);

class THandle
{
    T handle;
public:
    THandle() 
      : handle(acquire_T()) {}
    ~THandle() { release_T(handle); }
    THandle(const THandle &) = delete;
    THandle(THandle && other) 
      : handle(other.handle) 
    { other.handle = {}; }
    THandle & operator=(const THandle &) = delete;
    THandle & operator=(THandle && other)
    { std::swap(handle, other.handle); }
}

class A
{
    std::string nameParent = "A";
    std::size_t bufferSizeParent = 0;
    THandle tParent;

public:
    A() {}
    A(std::string tNameParent, std::size_t tBufferSizeParent) : nameParent(tNameParent), bufferSizeParent(tBufferSizeParent)
    { }

    virtual ~A() = default;
    A(const A &) = default;
    A(A &&) = default;
    A & operator=(const A &) = default;
    A & operator=(A &&) = default;

    virtual string getName()                    { return nameParent; }
    virtual void setName(const string name)     { nameParent = name; }
};

class B : public A
{
    std::string nameChild = "B";
    std::size_t bufferSizeChild = 0;
    THandle tChild;

public:
    B() {}
    B(string tNameChild, string tNameParent, size_t tBufferSizeChild, size_t tBufferSizeParent) 
    : A(tNameParent, tBufferSizeParent), nameChild(tNameChild), bufferSizeChild(tBufferSizeChild), bufferChild(std::make_unique(tBufferSizeChild))
    { }

    virtual string getName() override final             { return nameChild; }
    virtual void setName(const string name) override final  { nameChild = name; }
};