代码之家  ›  专栏  ›  技术社区  ›  Horst Walter

冲突的CLANG`virtual dtor`和`deprecated copy operator`警告

  •  1
  • Horst Walter  · 技术社区  · 6 年前

    在我的Qt项目中,我有一个类如下。我得到以下警告(已理解),并添加一个虚拟dtor。

    dbmappingcomponentaware.h:25: warning: CDbMappingComponentAware has virtual functions but non-virtual destructor

    现在我明白了

    warning: definition of implicit copy assignment operator for 'CDbMappingComponentAware' is deprecated because it has a user-declared destructor

    这个类是一个普通的类,我没有声明任何运算符。我该如何解决这场冲突?

    截至 How to disable implicitly-defined copy constructor generation when there is user defined destructor 看起来我不得不接受“不赞成”的警告,但我不确定。

    //! Allows subcomponents to gain access to model component
    class CDbMappingComponentAware {
      public:
        //! Destructor (added for 1st warning)
        // virtual ~CDbMappingComponentAware() {}
    
        //! Set the corresponding component
        virtual void setMappingComponent(CDbMappingComponent *component);
    ...
    ...
    

    --编辑,基于注释--

    https://en.cppreference.com/w/cpp/language/copy_assignment 上面写着,

    隐式定义的复制分配运算符的生成是 用户声明的复制构造函数。

    但这是为什么?我是说,为什么数码相机会影响复印员?

    1 回复  |  直到 6 年前
        1
  •  1
  •   user1810087 Akin Ocal    6 年前

    至于如何在存在用户定义的析构函数时禁用隐式定义的复制构造函数生成,看起来我必须接受“deprecated”警告,但我不确定。

    您不必接受“已弃用”警告。你有三个选择, 实施 接线员, 显式默认 操作员或 删除 接线员。

    首先,这个警告是触发器,因为您实际上使用 copy assignment operator //unfortunate mistake 在下面的示例中)。实际上,除了使用操作符的警告之外,还应该得到一个注释,例如:

    note: in implicit copy assignment operator for 'CDbMappingComponentAware' first required here
    

    考虑下面的例子( running version ):

    class foo {
    public:
        virtual ~foo() {}
    
        // options
        // implement
        //foo& operator=(foo const&) {return *this;}
        // default
        //foo& operator=(foo const&) = default;
        // delete
        //foo& operator=(foo const&) = delete;
    };
    
    class bar : public foo {
    public:
        ~bar() override {};
    };
    
    // stupid mistake... should be defined
    // void fn(bar const&)
    void fn(bar) {}
    
    
    int main(int, char*[]) {
        foo* f1 = new bar;
        foo* f2 = new bar;
    
        // triggers warning
        *f1 = *f2;
    
        // unfortunate mistake
        bar b;
        // triggers warning twice since bar inherits from foo
        fn(b);
    
        return 0;
    }
    

    复制分配运算符 ,你也应该 它,或者 如果真的是 普通香草 . 看看下面为什么你最终不应该违约。如果你根本不想复制实例, 删除 操作员/ctor。

    顺便说一下,复制构造函数也是一样的,不仅仅是赋值运算符。它在 §15.8.1/6节 对于复制构造函数和 用于草稿中的副本分配运算符 n4727 .

    但这并不意味着如果我定义了一个虚拟dtor,我就不能复制一个对象(除非我显式地编写了一个复制赋值操作符)。

    不,只要生成的复制ctor/assignment是一个警告,您仍然可以使用它。贬低意味着它(将来可能)会成为一个错误(如果C++的话,可能在大约40年或更长时间内,如果有的话)。因此,如果您不希望代码将此警告作为错误发送,当编译器不再支持它时,您应该立即修复它。


    但这是为什么?我是说,为什么数码相机会影响复印员?

    假设答案如下:

    我能想到的一个目的是防止一些错误。举个例子(摘自 Why doesn’t my constructor work right? ):

    class Handle {
    private:
        string name;
        X* p;
    public:
        Handle(string n)
            :name(n), p(0) { /* acquire X called "name" and let p point to it */ }
        ~Handle() { delete p; /* release X called "name" */ }
    };
    void f(const string& hh)
    {
        Handle h1(hh);
        Handle h2 = h1; // leads to disaster!
    }
    

    为了防止双重删除,您必须明确,而不是依赖 生成 / 违约的

    你是说警告是为了执行三条规则吗?

    在这种情况下: 是的

    因为我不处理资源问题,所以这里的“三个原则”没有真正意义。

    个人想法:

    恕我直言,我不相信这会成为一个错误的C++。依赖于自动生成的ctor/assignment,有很多代码可以使用。犯这个错误会破坏(字面上)成堆的项目。->不会发生。。。