C ++ - 成员对象中枚举的行为

时间:2013-03-28 05:21:03

标签: c++ qt class pointers member

我在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.

8 个答案:

答案 0 :(得分:9)

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

MemberClass添加显式默认构造函数:

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

或成员初始化为ParentClass

ParentClass::ParentClass(QObject *parent) :
    QObject(parent), objectMember(NULL)
{
    pointerMember = new MemberClass(this);
}

答案 1 :(得分:1)

在您的会员声明中

private:
    MemberClass objectMember;

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

答案 2 :(得分: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;
}

您可以看到结果here

答案 3 :(得分:0)

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

MemberOfMyClass member;

当你超出范围时,你的对象信息就会丢失

答案 4 :(得分:0)

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

答案 5 :(得分:0)

我只是将您的代码复制并粘贴到一个干净的项目中。使用MSVC2010使用Qt 4.8.0编译时,一切看起来都很正常。你重建了你的项目并重新运行qmake吗?

答案 6 :(得分:0)

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

答案 7 :(得分:0)

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

会发生什么
objectmember = *pointerMember;
初始化pointerMember后,

到构造函数?我玩过C ++已经有点了,所以我可能会遗漏一些明显的东西,但我敢打赌这是你的问题。

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

相关问题