我有几个我不想复制的类,其中一些类有指针数据成员。为了使这些类不可复制,我私下继承了以下类模板:
template <class T>
class Uncopyable
{
protected:
Uncopyable() {}
virtual ~Uncopyable() {}
private:
Uncopyable(const Uncopyable &);
T & operator=(const T&);
};
我使用的是这样的:
class Entity : private Uncopyable<Entity> { }
这很好用,但是当我用-Weffc ++编译时,我仍然会收到以下警告:
class Entity has pointer data members
but does not override Entity(const Entity&)
or operator=(const Entity&)
为什么它仍然给我这个警告?
答案 0 :(得分:9)
C ++说
因为复制赋值运算符是 如果没有由用户声明,则为类隐式声明,基类复制赋值运算符始终是 由派生类的复制赋值运算符隐藏(13.5.3)。带来的使用声明(7.3.3) 从基类中赋予赋值运算符,其参数类型可以是复制赋值的参数类型 派生类的运算符不被视为复制赋值运算符的显式声明 不会抑制派生类复制赋值运算符的隐式声明; using声明引入的运算符由隐式声明的复制赋值运算符隐藏 衍生类。
代码中的错误是您的基类声明operator=
接受派生类类型的引用。这不会阻止对基础的运算符=的隐式公开声明。因此,您的派生类和仍然是可分配的。尝试将不可复制的类更改为非模板,这应该足够了:
class Uncopyable
{
protected:
Uncopyable() {}
virtual ~Uncopyable() {}
private:
Uncopyable(const Uncopyable &);
Uncopyable & operator=(const Uncopyable&);
};
我刚才在该代码中想到的另一件事:不要将Uncopyable的析构函数设为虚拟。原因是,没有人(除了派生类本身)可以在指向Uncopyable的指针上调用delete(因为1:析构函数受到保护,2:你私有派生)。因此,Uncopyable的关注点并不是使派生类的析构函数隐式虚拟化。如果派生类需要有一个虚拟析构函数,那么将虚拟析构函数放在那里,并使Uncopyables的析构函数非虚拟化。