使用“Uncopyable”类时,会消除GCC警告

时间:2021-10-13 16:54:54

I have several classes that I don't want to be copyable, some of these classes have pointer data members. To make these classes uncopyable I privately inherit the following class template:

我有几个我不想复制的类,其中一些类有指针数据成员。为了使这些类不可复制,我私下继承了以下类模板:

template <class T>
class Uncopyable
{
  protected:
    Uncopyable() {}
    virtual ~Uncopyable() {}
  private:
    Uncopyable(const Uncopyable &);
    T & operator=(const T&);
};

Which I used like so:

我这样使用的是:

class Entity : private Uncopyable<Entity> { }

This works fine, however when I compile with -Weffc++ I still get the following warning:

这工作正常,但是当我用-Weffc ++编译时,我仍然收到以下警告:

class Entity has pointer data members
but does not override Entity(const Entity&)
or operator=(const Entity&)

Why is it still giving me this warning?

为什么它仍然给我这个警告?

1 个解决方案

#1


C++ says

Because a copy assignment operator is implicitly declared for a class if not declared by the user, a base class copy assignment operator is always hidden by the copy assignment operator of a derived class (13.5.3). A using-declaration (7.3.3) that brings in from a base class an assignment operator with a parameter type that could be that of a copy-assignment operator for the derived class is not considered an explicit declaration of a copy-assignment operator and does not suppress the implicit declaration of the derived class copy-assignment operator; the operator introduced by the using-declaration is hidden by the implicitly-declared copy-assignment operator in the derived class.

因为如果未由用户声明,则为类隐式声明复制赋值运算符,则基类复制赋值运算符始终由派生类的复制赋值运算符隐藏(13.5.3)。 using-declaration(7.3.3)从基类引入赋值运算符,其参数类型可以是派生类的副本赋值运算符的参数类型,不被视为复制赋值运算符的显式声明不会抑制派生类复制赋值运算符的隐式声明; using-declaration引入的运算符由派生类中隐式声明的复制赋值运算符隐藏。

The bug in the code is that your base class declares the operator= to accept a reference of type of the derived class. That won't prevent an implicit public declaration of an operator= for the base. Thus, your derived class and your base class are still assignable. Try changing your noncopyable class into a non-template, which should suffice:

代码中的错误是您的基类声明operator =接受派生类类型的引用。这不会阻止对基础的运算符=的隐式公开声明。因此,派生类和基类仍可分配。尝试将不可复制的类更改为非模板,这应该足够了:

class Uncopyable
{
  protected:
    Uncopyable() {}
    virtual ~Uncopyable() {}
  private:
    Uncopyable(const Uncopyable &);
    Uncopyable & operator=(const Uncopyable&);
};

One more thing i have just figured in that code: Don't make the destructor of Uncopyable virtual. The reason is, no-one (apart from the derived class itself) can call delete on a pointer to Uncopyable (because 1: the destructor is protected, 2: you derive privately). So it's not the concern of Uncopyable to make the destructor of the derived class implicitly virtual. If the derived class needs to have a virtual destructor, put virtual in there instead, and leave Uncopyables' destructor non-virtual.

我刚才在代码中想到的另一件事:不要使Uncopyable的析构函数变为虚拟。原因是,没有人(除了派生类本身)可以在指向Uncopyable的指针上调用delete(因为1:析构函数受到保护,2:你私有派生)。因此,Uncopyable的关注点不是使派生类的析构函数隐式虚拟化。如果派生类需要具有虚拟析构函数,则将虚拟析构放在那里,并使Uncopyables的析构函数非虚拟化。

#1


C++ says

Because a copy assignment operator is implicitly declared for a class if not declared by the user, a base class copy assignment operator is always hidden by the copy assignment operator of a derived class (13.5.3). A using-declaration (7.3.3) that brings in from a base class an assignment operator with a parameter type that could be that of a copy-assignment operator for the derived class is not considered an explicit declaration of a copy-assignment operator and does not suppress the implicit declaration of the derived class copy-assignment operator; the operator introduced by the using-declaration is hidden by the implicitly-declared copy-assignment operator in the derived class.

因为如果未由用户声明,则为类隐式声明复制赋值运算符,则基类复制赋值运算符始终由派生类的复制赋值运算符隐藏(13.5.3)。 using-declaration(7.3.3)从基类引入赋值运算符,其参数类型可以是派生类的副本赋值运算符的参数类型,不被视为复制赋值运算符的显式声明不会抑制派生类复制赋值运算符的隐式声明; using-declaration引入的运算符由派生类中隐式声明的复制赋值运算符隐藏。

The bug in the code is that your base class declares the operator= to accept a reference of type of the derived class. That won't prevent an implicit public declaration of an operator= for the base. Thus, your derived class and your base class are still assignable. Try changing your noncopyable class into a non-template, which should suffice:

代码中的错误是您的基类声明operator =接受派生类类型的引用。这不会阻止对基础的运算符=的隐式公开声明。因此,派生类和基类仍可分配。尝试将不可复制的类更改为非模板,这应该足够了:

class Uncopyable
{
  protected:
    Uncopyable() {}
    virtual ~Uncopyable() {}
  private:
    Uncopyable(const Uncopyable &);
    Uncopyable & operator=(const Uncopyable&);
};

One more thing i have just figured in that code: Don't make the destructor of Uncopyable virtual. The reason is, no-one (apart from the derived class itself) can call delete on a pointer to Uncopyable (because 1: the destructor is protected, 2: you derive privately). So it's not the concern of Uncopyable to make the destructor of the derived class implicitly virtual. If the derived class needs to have a virtual destructor, put virtual in there instead, and leave Uncopyables' destructor non-virtual.

我刚才在代码中想到的另一件事:不要使Uncopyable的析构函数变为虚拟。原因是,没有人(除了派生类本身)可以在指向Uncopyable的指针上调用delete(因为1:析构函数受到保护,2:你私有派生)。因此,Uncopyable的关注点不是使派生类的析构函数隐式虚拟化。如果派生类需要具有虚拟析构函数,则将虚拟析构放在那里,并使Uncopyables的析构函数非虚拟化。