"QObject::QObject"无法访问在类"QObject"中声明的私有成员。

23
class CHIProjectData : public QObject
{
public:
    CHIProjectData();
    CHIProjectData(QMap<QString,QString> aProjectData,
                   CHIAkmMetaData* apAkmMetaData = 0,
                   QObject* parent = 0);
private:
    QMap <QString,QString> m_strProjectData;
    CHIAkmMetaData* m_pAkmMetaData;
};

CHIProjectData::CHIProjectData(QMap<QString,QString> aProjectData,
                               CHIAkmMetaData* apAkmMetaData,
                               QObject* aParent)
    :
    QObject(aParent)
{
        m_strProjectData = aProjectData;
        m_pAkmMetaData = apAkmMetaData;
}

为什么会出现“'QObject::QObject' 无法访问类 'QObject' 中声明的私有成员”错误?


2
什么导致了这个错误?哪一行触发了它? - CB Bailey
为什么不使用初始化列表来初始化所有成员? - GManNickG
@Charles:错误指向CHIProjectData类声明的最后一行。 - Sulla
@Charles:将QObject作为基类添加会触发错误。之前没有基类时程序运行正常。 - Sulla
2
@Arun:那好像不对。只有在某些情况下使用默认构造函数时才会触发错误。你的默认构造函数定义在哪里? - CB Bailey
是的,缺省构造函数实现会很有趣。 - Frank Osterfeld
5个回答

30
我猜测你的CHIProjectData类被复制到了某个地方(使用编译器生成的复制构造函数或赋值运算符)。QObject无法被复制或赋值,因此会导致错误。但是,编译器没有明确指出错误发生的位置,所以它会选择文件中的某一行(通常是最后一个括号),因为在解析类声明后,编译器才知道是否需要生成这些函数。

3
谢谢,那正是我的问题,尽管复制QObject的行在另一个代码文件中。(而且它也隐藏在myObject = MyObjectClass()中。) - Martin Hennings

13

QObject 的默认构造函数必须是私有的,而您遇到的错误很可能与 CHIProjectData::CHIProjectData(默认构造函数)试图隐式地调用其基类的默认构造函数有关。如果您查看 QObject,您很可能会发现它定义了类似于以下内容:

class QObject {
    QObject(); //private contructor, derived classes cannot call this constructor
public:
    QObject(QObject* aParent);
};

解决方案是将默认的QObject构造函数设置为受保护或公共,或从默认的CHIProjectData构造函数调用其他构造函数重载:

CHIProjectData::CHIProjectData() : QObject(NULL){
}

或者将aProjectData默认设置为QMap<QString,QString>(),这样您就可以免费获得默认构造函数。 - GManNickG
1
好的理论,但是QObject的唯一构造函数是公共的:QObject(QObject* parent=0)。而改变Qt的API并不是一个真正的选择。 - Mike Seymour

4
在CHIProjectData类中添加一个复制构造函数就解决了问题。

4
请注意,除非您在拷贝构造函数中执行更多的工作来从原始实例的QObject父项复制设置到新实例的QObject父项,否则您并没有完全复制CHIProjectData。这包括信号和槽连接等内容。 - Caleb Huitt - cjhuitt

3

在使用QObject子类对象时,请尽量使用指针进行操作。

考虑以下问题场景:

myObject = MyObjectClass() 

在这种情况下,更加清晰的做法是保持原样。
MyObjectClass *myObject;
//code
myObject = new MyObjectClass;

这将通过使用引用复制和赋值来消除对象复制和赋值的需要。

1
在我的情况下,问题出在 Q_OBJECT 宏会在结构体内部悄悄地引入 private: 限定符:
struct myClass : public QObject {
   Q_OBJECT
   // everything here is private now...
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接