2

我在 C++ 中使用 Qt 并且正在努力解决枚举问题。考虑一个类似下面的案例:

在 GitHub 上克隆:https ://github.com/jif/enum

// memberclass.h =======================================================
#ifndef MEMBERCLASS_H
#define MEMBERCLASS_H

#include <QObject>

class MemberClass : public QObject
{
    Q_OBJECT
public:
    enum ErrorType {
        NoError,
        IsError
    };
    explicit MemberClass(QObject *parent = 0);
    void setError(ErrorType errorType);
    MemberClass::ErrorType error() const;
    void otherMethod();
private:
    MemberClass::ErrorType mError;
};

#endif // MEMBERCLASS_H

// memberclass.cpp =======================================================
#include "memberclass.h"
#include <QDebug>

MemberClass::MemberClass(QObject *parent) :
    QObject(parent)
{
    mError = NoError;
    qDebug() << "mError initialized.";
}
MemberClass::ErrorType MemberClass::error() const {
    return mError;
}
void MemberClass::setError(ErrorType errorType) {
    mError = errorType;
}
void MemberClass::otherMethod() {
    qDebug() << "    In otherMethod()...";
    qDebug() << "      mError = " << mError;
    qDebug() << "      NoError = " << NoError;
    qDebug() << "      IsError = " << IsError;
    qDebug() << "    End otherMethod()";
}

// parentclass.h =======================================================
#ifndef PARENTCLASS_H
#define PARENTCLASS_H

#include <QObject>
#include "memberclass.h"

class ParentClass : public QObject
{
    Q_OBJECT
public:
    explicit ParentClass(QObject *parent = 0);
    void testEnumStuff();
private:
    MemberClass objectMember;
    MemberClass *pointerMember;
};

#endif // PARENTCLASS_H

// parentclass.cpp =======================================================
#include "parentclass.h"
#include <QDebug>

ParentClass::ParentClass(QObject *parent) :
    QObject(parent)
{
    pointerMember = new MemberClass(this);
}
void ParentClass::testEnumStuff() {
    qDebug() << "Just initialized...";
    qDebug() << "  pointerMember::mError = " << pointerMember->error();
    qDebug() << "  objectMember::mError =  " << objectMember.error();
    qDebug() << "Calling otherMethod() on each member...";
    qDebug() << "  In pointerMember...";
    pointerMember->otherMethod();
    qDebug() << "  In objectMember...";
    objectMember.otherMethod();
    qDebug() << "  pointerMember::mError = " << pointerMember->error();
    qDebug() << "  objectMember::mError =  " << objectMember.error();
    qDebug() << "Done.";
}

// main.cpp =======================================================
#include <QCoreApplication>
#include "parentclass.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    ParentClass parent;
    parent.testEnumStuff();
    return a.exec();
}


// enum.pro =======================================================
QT       += core

QT       -= gui

TARGET = enum
CONFIG   += console
CONFIG   -= app_bundle

TEMPLATE = app


SOURCES += main.cpp \
    parentclass.cpp \
    memberclass.cpp

HEADERS += \
    parentclass.h \
    memberclass.h

mError使用类型变量ErrorType不能按预期工作(它在执行过程中会出现奇怪且不一致的值)。

我得到这样的输出:

mError initialized.
mError initialized.    
Just initialized... 
  pointerMember::mError =  0 
  objectMember::mError =   0 
Calling otherMethod() on each member... 
  In pointerMember... 
    In otherMethod()... 
      mError =  0 
      NoError =  0 
      IsError =  1 
    End otherMethod() 
  In objectMember... 
    In otherMethod()... 
      mError =  13498688 
      NoError =  0 
      IsError =  1 
    End otherMethod() 
  pointerMember::mError =  0 
  objectMember::mError =   13498688 
Done.
4

8 回答 8

10

您没有定义默认构造函数,MemberClass编译器提供的隐式构造函数用于objectMemberParentClass. 隐式构造函数不会mError为您初始化,因此您获得的随机值。

将显式默认构造函数添加到MemberClass

MemberClass::MemberClass() :
    QObject(NULL), mError(NoError)
{
}

或成员初始化ParentClass

ParentClass::ParentClass(QObject *parent) :
    QObject(parent), objectMember(NULL)
{
    pointerMember = new MemberClass(this);
}
于 2013-04-02T03:48:05.743 回答
1

在您的成员声明中

private:
    MemberClass objectMember;

您没有为构造函数提供参数。它正在调用 QObject 的默认构造函数(不在您的代码中)并且不会初始化枚举。

于 2013-04-02T15:35:42.413 回答
1

我只是将您的代码复制并粘贴到一个干净的项目中。当使用 MSVC2010 使用 Qt 4.8.0 编译时,我觉得一切正常。您是否重建了项目并重新运行了 qmake?

于 2013-04-05T20:15:30.683 回答
1

我克隆了你的代码运行它,没有问题。
我建议你清理你的项目并重新构建它。代码看起来也不错。我认为编译器缓存在代码修改期间被损坏(有时会发生)并且生成了错误的代码,干净的项目应该修复它。

于 2013-04-07T18:42:36.387 回答
1

实际上,您并没有获得自动生成的构造函数。这样做的原因是,您只会在一个根本没有定义构造函数的类中获得这样的构造函数。您为 MemberClass(QObject *parent = 0) 定义了一个构造函数,但是因为它存在,所以没有为您分配一个自动生成的 noargs 构造函数。

一个类似但相关的例子可以说明问题的类别:

class Base
{
    /*Has a constructor therefore does not get a free 
     noargs constructor*/
    Base(int i) {}; 
};

class Derived : public Base
{
};

int main()
{
     /*Not actually possible because Derived will get a free noargs constructor
       which will attempt to invoke the non existant no args constructor of Base.
     */
     Derived d; 

     return 0;
}

你可以在这里看到结果

于 2013-04-08T12:58:38.943 回答
0

如果您在堆栈上定义对象,例如:

MemberOfMyClass member;

当您超出范围时,您的对象信息将丢失

于 2013-03-28T05:45:05.447 回答
0

MemberClass 单参数构造函数具有行 << "mError initialized."; 输出中没有。编译器生成的默认构造函数对成员变量的期望值一无所知,所以如果为这些分配的内存有垃圾,这个垃圾就会泄露。

于 2013-04-02T19:15:18.610 回答
0

您永远不会在 ParentClass 的构造函数中初始化“objectMember”值,但您确实初始化了“pointerMember”。我敢打赌,“objectMember”也是在测试中给您带来问题的价值,这不是巧合。我没有 QT,但是如果你添加会发生什么

objectmember = *pointerMember;

初始化指针成员后到构造函数?自从我玩过 C++ 以来已经有一段时间了,所以我可能遗漏了一些明显的东西,但我敢打赌这是你的问题。

另请注意,上次我使用它时,Visual Studio 的调试器倾向于为程序员将所有未初始化的值设置为 0。一旦实际编译了代码,就不会发生这种情况(尽管我相信某些编译器可能会这样做,例如 GCC),因此这可能就是您看到此错误而其他人没有看到的原因。因此,将您要查找的值设为“IsError”可能会有所帮助 - 这样,您要查找的值将是 1,而不是默认的未初始化值。

于 2013-04-08T05:09:20.643 回答