我对编译器警告感到困惑。我使用了 MinGW 5.3.0 32bit 并尝试编译此代码:
#include <QCoreApplication>
#include <QObject>
#include <QDebug>
class A : public QObject
{
Q_OBJECT
public:
A(QObject* parent = 0){ Q_UNUSED(parent);}
~A() {qDebug()<<"~A()";}
virtual void func(){}
private:
};
class B : public A
{
Q_OBJECT
public:
B(){}
B (const B & object) {/*do somthing*/}
~B(){}
void func(){/*do somthing*/}
private:
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
return a.exec();
}
Run Code Online (Sandbox Code Playgroud)
我的编译器告诉我:
在复制构造'B :: B(常数B&)':警告:基类的类A'应在复制构造明确初始化[-Wextra] B(const的B&对象){/做财产以后/} ^
怎么了?
对于手动复制构造函数(即您的B::B(const B &)),在实践中依赖A被调用的默认构造函数是不寻常的(尽管在标准 C++ 中技术上不是非法的)- 如果您在B没有显式初始化的情况下实现复制构造函数,则会发生这种情况在A中的初始化器列表B构造函数。
您的编译器配置为警告此类事情。这是编译器的实施质量问题(在这种情况下,他们不需要发出警告)。但是,实际上,您的编译器供应商正在帮您一个忙。
你的复制构造函数 B
B (const B & object) {/*do somthing*/}
Run Code Online (Sandbox Code Playgroud)
实际上相当于
B (const B & object) : A() {/*do somthing*/}
Run Code Online (Sandbox Code Playgroud)
正如我上面所说,在实践中明确地这样做是不寻常的 - 这很少是一种理想的行为。
关闭编译器以使其不发出此警告的方法是A在Bs 构造函数的初始化列表中显式构造。你可以像上面那样使用默认构造函数A(理论上,它可能会或可能不会阻止编译器抱怨),但更常用的技术类似于
B (const B & object) : A(object) {/*do somthing*/}
Run Code Online (Sandbox Code Playgroud)
请记住, 的复制构造函数A将在B构造函数体之前调用(即首先构造基类)。
更好的是,如果可能,您最好根本不定义复制构造函数。在这种情况下(假设某些东西不会阻止它这样做,例如private基类的复制构造函数),编译器将自动生成一个复制构造函数,用于B使用它们的复制构造函数(递归地)初始化其所有基类及其所有数据成员。
您正在为 B 类编写复制构造函数,但您的父类 A 是默认构造的。我(大概还有编译器)希望 B 的复制构造函数也复制构造其父级。鉴于 A 中有析构函数和虚函数,您应该认真考虑为 A 创建复制构造函数或完全禁用它。
| 归档时间: |
|
| 查看次数: |
3921 次 |
| 最近记录: |