WZX's blog 海滩上捡贝壳的孩子

复制构造函数

2019-08-30
wzx
 

在 QT 中,自定义类放入QList时,编译时报错 'PanelItem::PanelItem(const PanelItem &)': attempting to reference a deleted function

分析解决

在调用QList::append(const T &value)增加元素的时候,内部存在对添加值的复制,调用了复制构造函数。这就是编译时出错,静态检查不出错的原因。

PanelItem 是自定义类,继承了 QGraphicsItem,乍一看编译器应该自动生成复制构造函数才对,但是 QGraphicsItem 继承了 QGraphicsObjectQGraphicsObject 继承了QObjectQObject弃置了复制构造函数,所以我们的自定义的拷贝构造函数也被弃置了

知道了原因,解决也很简单。自定义复制构造函数,或者干脆在QList存指针

复制构造函数

显式复制构造函数

自定义复制构造函数时,需要遵守,类 T 的复制构造函数是非模板构造函数,其首个形参为 T&const T&volatile T&const volatile T&,而且要么没有其他形参,要么剩余形参均有默认值

通过以下代码,规定编译器行为

  • class_name ( const class_name & ) = default; 强制编译器生成默认的构造函数
  • class_name ( const class_name & ) = delete; 强制编译器阻止隐式复制构造函数

隐式复制构造函数

若没有显式的定义复制构造函数,编译器会附加隐式声明的复制构造函数 当以下各项均为真时,这个隐式声明的复制构造函数拥有形式 T::T(const T&)

  • T 的每个直接与虚基类 B 均拥有复制构造函数,其形参为 const B& 或 const volatile B&
  • T 的每个类类型或类类型数组的非静态数据成员 M 均拥有复制构造函数,其形参为 const M&const volatile M& 否则,隐式声明的复制构造函数是 T::T(T&)

丢弃的隐式复制构造函数

若下列任何条件为真,编译器会附加 class_name ( const class_name & ) = delete;(c++11)

  • T 拥有无法复制的非静态数据成员(拥有被弃置、不可访问或有歧义的复制构造函数)
  • T 拥有无法复制的父类或虚基类(拥有被弃置、不可访问或有歧义的复制构造函数)
  • T 拥有带被弃置或不可访问的析构函数的父类或虚基类
  • T 是联合式的类,且拥有带非平凡复制构造函数的变体成员
  • T 拥有右值引用类型的数据成员
  • T 拥有用户定义的移动构造函数或移动赋值运算符(此条件只导致隐式声明的,而非预置的复制构造函数被弃置)

平凡复制构造函数

当下列各项全部为真时,类 T 的复制构造函数为平凡的:

  • 它不是用户提供的(即它是隐式定义或预置的),且若它被预置,则其签名与隐式定义的相同
  • T 没有虚成员函数;
  • T 没有虚基类;
  • T 的每个直接基类选择的复制构造函数都是平凡的;
  • T 的每个类类型(或类类型数组)的非静态成员选择的复制构造函数都是平凡的;

调用情形

当类的对象需要拷贝时,复制构造函数将会被调用。以下情况都会调用复制构造函数:

  • 一个对象以值传递的方式传入函数体
  • 一个对象以值传递的方式从函数返回
  • 一个对象需要通过另外一个对象进行初始化

下一篇 QT绘图体系

Comments

Content