1

クラスがあり、そのオブジェクトは次のように別のクラスで使用されます

class A
{
public:
    void F() {...}
};

class B
{
public:
    void G() { m_a->F(); ...} // use A's function

private:
    A* m_a;
};

したがって、ポインター m_a の代入の前に B::G() を呼び出すのは間違っています。これは受け入れられるデザインですか?または、それを行うより良い方法があります。

質問は、GUI アプリケーションの開発から来ています。メイン ウィンドウの下にウィンドウがあり、現在の操作の基本情報 (何が起こっているか、どれくらい時間がかかるかなど) を表示します。どこにでも散らばる可能性のある操作で簡単にアクセスできるように、このウィンドウをシングルトンとして配置し、GUI アプリケーションを閉じるときにコードがクラッシュすることを発見しました。クラッシュは、GUI アプリケーション (Qt の qApp など) の削除後にウィンドウが削除されることが原因です。次に、ウィンドウの参照ポインターをシングルトンに配置します。ウィンドウが構築されたら、参照ポインターを設定します。ウィンドウの削除は、メイン ウィンドウによって制御されます。したがって、上記のクラッシュの問題は解決されます。ただし、ウィンドウが構築される前に他の開発者がシングルトンを使用すると、コードもクラッシュします。それを解決する良い方法はありますか?それとも、構築する前にそれを使用するのは開発者の間違いであるため、そのまま受け入れることができますか? どうもありがとう!

4

3 に答える 3

3

が初期化されていない場合、関数を呼び出すG()と未定義の動作が発生する可能性があるためm_a、そうでないことを確認する必要があります。コードを次のように変更する必要があります。

class B
{

public:

    B() : m_a(nullptr) { } // m_a always initialized!

    bool G() 
    { 
        if (m_a == nullptr) return false; // No Undefined Behavior!
        m_a->F(); // This call is safe now
        ...
        return true;
    }

private:

    A* m_a;

};

ところで、一般的には、正当な理由がない限り、生のポインターではなくスマート ポインター (適切な所有権のセマンティクスを実現する型を選択する) を使用する必要があります。これにより、手動で初期化する必要がなくなります (ここでは所有権が共有されていると仮定します)。

#include <memory>

class B
{

public:

    bool G() 
    { 
        if (m_a == nullptr) return false; // No Undefined Behavior!
        m_a->F(); // This call is safe now
        ...
        return true;
    }

private:

    std::shared_ptr<A> m_a; // Automatically initalized to nullptr

};
于 2013-01-31T15:52:53.450 に答える
2

メンバー初期化子リストを使用して、割り当てるのではなく初期化する必要があります。これにより、他の関数を呼び出す前に割り当てを気にする必要がなくなります。 m_am_a

于 2013-01-31T15:47:35.723 に答える
1

予想されるクラスの使用方法によっては、これは許容される方法ですが、そうする場合は、B::G()最初にポインターをチェックするように変更することをお勧めします。

void G() { if (m_a) m_a->F(); ...}

m_aまた、現在指し示す実数がない場合は、すべてのコンストラクターで少なくとも null ポインターに初期化するようにしてくださいA

于 2013-01-31T15:53:36.990 に答える