gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 04:57:44 25 4
gpt4 key购买 nike

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

dbmappingcomponentaware.h:25: 警告:CDbMappingComponentAware 具有虚函数但非虚析构函数

现在我明白了

警告:“CDbMappingComponentAware”的隐式复制赋值运算符的定义已弃用,因为它具有用户声明的析构函数

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

截至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它说,

The generation of the implicitly-defined copy assignment operator is deprecated(since C++11) if T has a user-declared destructor or user-declared copy constructor.

但这是为什么呢?我的意思是,为什么 dtor 会影响复制运算符(operator)?

最佳答案

As of How to disable implicitly-defined copy constructor generation when there is user defined destructor it looks like I have to accept the "deprecated" warning, but I am not sure.

您不必接受“已弃用”警告。您在这里有 3 个选项,实现 运算符,显式默认 运算符或删除 运算符。

首先,触发此警告是因为您实际上在某处使用了复制赋值运算符。甚至可能不是故意的(参见下面示例中的 //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;
}

在这种情况下,您确实在使用复制赋值运算符,您应该实现它,或者默认它(如果确实如此) 纯 Vanilla 。请参阅下文为什么您最终不应该默认它。如果您根本不想复制实例,请删除运算符/构造函数。

顺便说一句,复制构造函数也是一样的,不仅仅是赋值运算符。复制构造函数在§15.8.1/6中描述,复制赋值运算符在§15.8.2/2中描述n4727 .

但是:

But would that not mean I cannot copy a object if I define a virtual dtor (unless I explicitly write a copy assignment operator).

不,你仍然可以使用生成的复制构造函数/赋值,只要它是一个警告。弃用意味着它将(可能)在未来成为一个错误(对于 C++,可能在大约 40 年或更长时间后,如果有的话)。因此,如果您不希望您的代码在编译器不再支持它时将此警告作为错误发出,您应该立即修复它。


But why is that? I mean, why is the dtor affecting the copy operator?

这里假设的答案:

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

Here, the default copy gives us h2.name==h1.name and h2.p==h1.p. This leads to disaster: when we exit f() the destructors for h1 and h2 are invoked and the object pointed to by h1.p and h2.p is deleted twice.

为防止双重删除,您必须明确且不依赖于生成的/默认的复制构造函数/赋值。

Are you saying the warning is there to enforce the rule of three?

在这种特殊情况下:,我会这么说。

As I do not deal with resources the rule of three does not make really sense here.

这将要求编译器考虑成员。为这样一个不成熟的警告付出了很多努力。

个人想法:

恕我直言,我不相信这会成为 C++ 中的错误。依赖于自动生成的构造函数/赋值,有很多代码可以使用。犯这个错误会破坏(字面上)数以千计的项目。 -> 不会发生...

关于c++ - 冲突的 CLANG `virtual dtor` 和 `deprecated copy operator` 警告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51971439/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com