代码之家  ›  专栏  ›  技术社区  ›  karafar

防止在复制构造函数中隐式调用基构造函数

  •  0
  • karafar  · 技术社区  · 7 年前

    我想阻止调用默认构造函数,这样就可以强制用户使用专门的构造函数。为此,我只需删除默认构造函数。

    当我想为派生类创建一个复制构造函数时,会出现一个问题。派生类的复制构造函数似乎隐式调用了父默认构造函数(已删除)。编译器不喜欢这样!

    有什么办法可以避免这种含蓄的呼吁吗?

    #include <iostream>
    
    class Base
    {
    public:
        Base() = delete;
    
        Base(int x)
        : _x(x)
        {
            std::cout << "Base's constructor" << std::endl;
        }
    
        Base(const Base &other)
        {
            std::cout << "Base's copy constructor" << std::endl;
            this->_x = other._x;
        }
    
    protected:
        int _x;
    };
    
    class Derived : public Base
    {
    public:
        Derived() = delete;
    
        Derived(int x, int y)
        : Base(x),  _y(y)
        {
            std::cout << "Derived's constructor" << std::endl;
        }
    
        Derived(const Derived &other)
        {
            // Implict call to Base(), which is deleted, and compilation fails.
            std::cout << "Derived's copy constructor" << std::endl;
            this->_x = other._x;
            this->_y = other._y;
        }
    
    protected:
        int _y;
    };
    
    int main(int argc, char** argv)
    {
        Derived d(10,10);
        Derived d2(d);
    }
    
    2 回复  |  直到 7 年前
        1
  •  4
  •   NathanOliver    7 年前

    您的问题是,由于所有构造函数都在进入构造函数体之前初始化其所有成员

    Derived(const Derived &other)
    {
        // Implict call to Base(), which is deleted, and compilation fails.
        std::cout << "Derived's copy constructor" << std::endl;
        this->_x = other._x;
        this->_y = other._y;
    }
    

    实际上是

    Derived(const Derived &other) : Base(), _y()
    {
        // Implict call to Base(), which is deleted, and compilation fails.
        std::cout << "Derived's copy constructor" << std::endl;
        this->_x = other._x;
        this->_y = other._y;
    }
    

    Base() 调用基类默认构造函数。

    您需要做的是利用成员初始值设定项列表来调用基类复制构造函数而不是默认构造函数。你用的是什么

    Derived(const Derived &other) : Base(other), _y(other._y)
    {
        // Implict call to Base(), which is deleted, and compilation fails.
        std::cout << "Derived's copy constructor" << std::endl;
        // this->_x = other._x; no longer needed as Base(other) takes care of _x
        // this->_y = other._y; no longer needed as _y(other._y) takes care of _y
    }
    

    您还应该更新 Base 的复制构造函数到

    Base(const Base &other) : _x(other._x)
    {
        std::cout << "Base's copy constructor" << std::endl;
    }
    

        2
  •  1
  •   Tim Randall    7 年前

    你不需要使用 =delete 防止调用默认构造函数。您可以使用前面的技术来声明它 private . 当然,在这种情况下,因为您希望它能够被派生类访问,所以您可以使它 protected

    但也可以显式构造所需的基类:

    Derived(const Derived &other)
        : Base(other._x)
        , _y(other._y)
    {
        std::cout << "Derived's copy constructor" << std::endl;
    }
    
    推荐文章