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

mErrortypeの変数の操作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

1

ここのメンバーの宣言で

private:
    MemberClass objectMember;

コンストラクターにパラメーターを提供していません。QObject (コードにはありません) のデフォルトのコンストラクターを呼び出しており、列挙型を初期化していません。

于 2013-04-02T15:35:42.413 に答える
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 に答える
1

コードをコピーしてクリーンなプロジェクトに貼り付けました。MSVC2010 を使用して Qt 4.8.0 でコンパイルすると、すべてが正常に見えました。プロジェクトを再構築して qmake を再実行しましたか?

于 2013-04-05T20:15:30.683 に答える
0

MemberClass の単一引数コンストラクターには行 << "mError initialized."; があります。それは出力にありません。コンパイラによって生成されたデフォルト コンストラクターは、メンバー変数に必要な値がわからないため、これらに割り当てられたメモリにガベージがある場合、このガベージがリークされます。

于 2013-04-02T19:15:18.610 に答える
0

ParentClass のコンストラクターで「objectMember」の値を初期化することはありませんが、「pointerMember」は初期化します。「objectMember」がテストで問題を引き起こす値でもあるのは偶然ではないと思います。私はQTを持っていませんが、追加するとどうなりますか

objectmember = *pointerMember;

pointerMember を初期化した後、コンストラクターに? C++ で遊んでから少し時間が経っているので、明らかな何かが欠けている可能性がありますが、これはあなたの問題だと思います。

また、最後に試してみたところ、Visual Studio のデバッガーは、プログラマーに対して初期化されていない値をすべて 0 に設定する傾向があることに注意してください。コードが実際にコンパイルされると、これは発生しません (ただし、GCC などの一部のコンパイラはそれを行う可能性があると思います)。そのため、このエラーが表示され、他のコンパイラでは表示されない可能性があります。このため、探している値を「IsError」にすることが役立つ場合があります。これにより、探している値はデフォルトの初期化されていない値ではなく、1 になります。

于 2013-04-08T05:09:20.643 に答える
0

次のようにスタックにオブジェクトを定義する場合:

MemberOfMyClass member;

範囲外に出ると、オブジェクト情報が失われます

于 2013-03-28T05:45:05.447 に答える