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

时间:2018-08-22 16:36:38

标签: c++ qt clang

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

Service Worker

现在我得到

class App extends React.Component{ render(){ return( <BrowserRouter> <Switch> <Route path="/" exact component={Home} /> <Route path="/profile" exact component={Profile} /> <Route path="/about" component={About}/> </Switch> </BrowserRouter> ); } } ReactDOM.render(<App/>,document.getElementById('root'));

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

How to disable implicitly-defined copy constructor generation when there is user defined destructor开始,看来我必须接受“已弃用”警告,但我不确定。

代码段:

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

-根据评论进行编辑-

阅读https://en.cppreference.com/w/cpp/language/copy_assignment上说,

  

隐式定义的副本分配运算符的生成为   不推荐使用(从C ++ 11开始),如果T具有用户声明的析构函数,或者   用户声明的副本构造函数。

那为什么呢?我的意思是,为什么dtor影响复制运算符?

1 个答案:

答案 0 :(得分:1)

  

从如何在存在用户定义的析构函数时禁用隐式定义的副本构造函数的生成开始,看来我必须接受“已弃用”警告,但我不确定。

您不必接受“已弃用”警告。您在此处有3个选项,实施运算符,默认默认运算符,或删除运算符。

首先,触发此警告是因为您实际上在某个地方使用了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;
}

在这种情况下,您实际上是在使用copy assignment operator,如果确实是纯香草,则应该实施默认 。参见下文,为什么您最终不应该默认它。如果您根本不想复制实例,请删除操作员/ ctor。

顺便说一句,对于复制构造函数,不仅是赋值运算符,它是相同的。草稿n4727中的副本构造函数§15.8.1/ 6 和副本赋值运算符§15.8.2/ 2 中对此进行了描述。

但是:

  

但这并不意味着如果定义了虚拟dtor,我将无法复制对象(除非我明确编写了一个复制赋值运算符)。

否,只要它是警告,您仍然可以使用生成的副本ctor /分配。弃用意味着将来(很可能)会出错(如果使用C ++,则可能会在大约40年或更长时间)。因此,如果您不希望您的代码将此警告吐为错误,那么当编译器不再支持该警告时,您应该立即进行修复。


  

那为什么呢?我的意思是,为什么dtor影响复制运算符?

此处的假设答案:

我能想到的一个目的是防止一些错误。考虑示例(摘自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!
}
  

在这里,默认副本为我们提供h2.name == h1.name和h2.p == h1.p。这导致灾难:退出f()时,将调用h1和h2的析构函数,并将h1.p和h2.p指向的对象删除两次。

为防止重复删除,您必须明确,而不要依赖生成的 / 默认副本构造函数/赋值。

  

您是说警告是要强制执行三个规则吗?

在这种情况下:,我会这样说。

  

因为我不处理资源,所以这里的三分法没有意义。

这将要求编译器考虑成员。对于这种不成熟的警告,我们付出了很大的努力。

个人想法:

恕我直言,我不相信这会成为C ++中的错误。有很多方法可以依靠自动生成的ctor / assignment来实现。使此错误会(从字面上)破坏项目的成堆。 ->不会发生...