質問

私自身もC++のコードでは複数のマオブジェクトのprivateなどの方法

void NotifyFooUpdated();

通話ができるの OnFooUpdated() 法のリスナーにこのオブジェクトです。

ご注意な変更の状態をこのオブジェクトのような技術的にする const 方法ものの、一般的になっている修正の状態のシステム全体として特に、リスナーオブジェクトが呼び返しにこのオブジェクトに変更することも出来ます。

個人的には思いもしない宣言し const.

しかし、静的コードチェッカーはQACこのフラグとして偏って宣言し const, はしていますが、なぜ彼らは非const、助成金の偏差値となっています。

何引数のない宣言これらの方法 const?
いや、あォQACすることを宣言し const?
きを採用し、厳重に地元の視点で制限されるこのオブジェクトのシステムかどうかはわかりません。

役に立ちましたか?

解決

大まかに言えば、コンテナクラスがあります:オブザーバーでいっぱいのマネージャー。 CおよびC ++では、コンスト以外の値を持つconstコンテナを使用できます。ラッピングの1つの層を取り外したかどうかを検討してください。

list<Observer> someManager;

void NotifyFooUpdated(const list<Observer>& manager) { ... }

リストを変更しないため、constリストを取得するグローバルなnotifyfooupoupdedについて奇妙なことは何も表示されません。そのconst引数は、実際には、解析をより許容する引数をより寛容にします。関数はconstリストと非constリストの両方を受け入れます。クラスメソッドバージョンのすべてのconstアノテーションは const *this.

別の視点に対処するには:

関数を呼び出したオブジェクトが、関数呼び出しの前後に同じままであることを保証できない場合は、通常、それを非コンストとして残す必要があります。

発信者がオブジェクトへの唯一の参照を持っている場合にのみ、それは合理的です。オブジェクトがグローバルである場合(元の質問にあるように)、またはねじ込み環境で、特定の呼び出しの競技は、オブジェクトの状態が呼び出し全体で変更されていないことを保証しません。副作用がなく、常に同じ入力に対して同じ値を返す関数は ピュア. 。 NotifyFOoupDate()は明らかに純粋ではありません。

他のヒント

リスナーがポインターのコレクションとして保存されている場合、オブジェクトがconstであっても、非コンストメソッドを呼び出すことができます。

契約が、リスナーが通知を受け取ったときに状態を更新することができる場合、メソッドは非コンストである必要があります。

リスナーはオブジェクトに呼び戻して変更できると言っています。しかし、リスナーはそれ自体を変更しません - したがって、Notifyコールはconstになる可能性がありますが、あなたは自分のオブジェクトに非コンストポインターを渡します。

リスナーがすでにそのポインターを持っている場合(それは1つのことだけに耳を傾けます)、オブジェクトが変更されることは副作用であるため、両方のメソッドconstを作成できます。起こっていることは次のとおりです。

結果として、呼び出しB Bが修正されます。

したがって、呼び出しBは間接的に独自の修正につながりますが、自己の直接的な変更ではありません。

これが当てはまる場合は、両方の方法がconstである可能性があり、おそらく必要です。

これらの方法を宣言しないことの議論は何ですか const?
または、QACに従って宣言する必要があります const?
このオブジェクトに制限された厳密にローカルな視点を採用するか、システム全体を考慮する必要がありますか?

あなたが知っていることは、そのマネージャーオブジェクトがこれを求められたということです いいえ 変化する。マネージャーが関数を呼び出すオブジェクト そうかもしれない 変更されるか、そうでないかもしれません。あなたはそれを知りません。

あなたの説明から、私はすべての関係するオブジェクトがあるようなデザインを想像することができます const (および通知は、コンソールに書き込むことで処理される場合があります)。この機能を作成しない場合 const, 、あなたはこれを禁止します。あなたがそれを作るなら const, 、両方を許可します。

これはこれを作ることに賛成する議論だと思います const.

関数を呼び出したオブジェクトが、関数呼び出しの前後に同じままであることを保証できない場合は、通常、それを非コンストとして残す必要があります。考えてみてください - リスナーを書いて、オブジェクトが非コンストである間に挿入してから、この関数を使用して、過去に非コンストだったときにそのオブジェクトにアクセスできたため、const正確性に違反することができます。それは間違っている。

私の考えは、彼らが残るべきだということです 非const. 。これは、マネージャーオブジェクトの状態は、実際には管理するすべてのオブジェクトの状態に加えて、本質的な状態、つまり、本質的な状態であるという私の認識に基づいています。 State(Manager) = State(Listener0) + State(Listener1) + ... + State(ListenerN) + IntrinsicState(Manager).

一方、ソースコードのカプセル化は、この実行時の関係を信じている場合があります。あなたの説明に基づいて、この集計状態はプログラムの実行時間動作を反映していると思います。

私の議論を強化するために:私は、コンピレーションの正確なセマンティクスを厳密に順守することを好むプログラムの実行時行動を反映するよう努力すべきであると主張します。

const, 、またはそうではありません const: :それが質問です。

の議論 const:

  • 問題の方法は、オブジェクトの状態を変更しません。
  • あなたの静的コードチェッカーは、憲法の欠如に偏差としてフラグを立てます。たぶんそれを聞くべきです。

反対の議論 const:

  • メソッドは、システム全体の状態を変更します。
  • リスナーはオブジェクトをオブジェクトします。オブジェクトを変更します。

個人的には、そのままにしておきます const, 、システム全体の状態を変更する可能性があるという事実は、ヌルポインターリファレンスに非常に似ています。それは const 方法では、問題のオブジェクトを変更しませんが、プログラムがクラッシュし、システム全体の状態が変更されます。

あ引数に対 const, こちらですか:-

個人的には思いませんこれらの"OnXXXUpdated"の一環として、マネージャー。これについては混乱が生じて最高です。だ知ら関係者約も、知らないかどうかの状態でオブジェクトは、今後どこへ向かおうとしている時に通知す。しれないし、しないかもしれません.何 明るいはその関係者に通知 すべ きconst.

なので、このジレンマこん:

を取り除くOnXXXXUpdated機能からマネージャー。

書が届き、このプロトタイプとし、以下の前提条件

"引数"には任意のベースのクラスについての情報が通知が起こる

"一般"には何らかの関数ポインタ(e.g FastDelegate).

class Args
{
};

class NotificationManager
{
private:
    class NotifyEntry
    {
    private:
        std::list<Delegate> m_Delegates;

    public:
        NotifyEntry(){};
        void raise(const Args& _args) const
        {
            for(std::list<Delegate>::const_iterator cit(m_Delegates.begin());
                cit != m_Delegates.end();
                ++cit)
                (*cit)(_args);
        };

        NotifyEntry& operator += (Delegate _delegate) {m_Delegates.push_back(_delegate); return(*this); };
    }; // eo class NotifyEntry

    std::map<std::string, NotifyEntry*> m_Entries;

public:
    // ctor, dtor, etc....

    // methods
    void register(const std::string& _name);     // register a notification ...
    void unRegister(const std::string& _name);   // unregister it ...

    // Notify interested parties
    void notify(const std::string& _name, const Args& _args) const
    {
        std::map<std::string, NotifyEntry*>::const_iterator cit = m_Entries.find(_name);
        if(cit != m_Entries.end())
           cit.second->raise(_args);
    }; // eo notify

    // Tell the manager we're interested in an event
    void listenFor(const std::string& _name, Delegate _delegate)
    {
        std::map<std::string, NotifyEntry*>::const_iterator cit = m_Entries.find(_name);
        if(cit != m_Entries.end())
            (*cit.second) += _delegate;
    }; // eo listenFor
}; // eo class NotifyManager

私は一部のコードとしてできるのではないでしょうかを伝えでご利用いただけます。いかねます。そしてこの通知の長いシングルトン.現在、確実に通知マネージャを作成し早く探しも、予約も、支払も、全部エの管理者だけで登録通知そのコンストラクタのようになります:

MyManager::MyManager()
{
    NotificationMananger.getSingleton().register("OnABCUpdated");
    NotificationMananger.getSingleton().register("OnXYZUpdated");
};


AnotherManager::AnotherManager()
{
    NotificationManager.getSingleton().register("TheFoxIsInTheHenHouse");
};

現在、マネージャーのニーズに通知関係者、その通話の通知:

MyManager::someFunction()
{
    CustomArgs args; // custom arguments derived from Args
    NotificationManager::getSingleton().notify("OnABCUpdated", args);
};

その他の授業を聴くことができたこと。

私は実感いただきました、入力のオブザーバーパターンが、私の意図したことに問題はどれも育てられているかどうかを、const状態です。による抽象化の過程を通知をmananagerクラスを受けて、通知が自由に変更するマネージャクラス。なに通知す。ことだと思います。

また、一本化することによる場所を通知はpraciceまぁ、これまでよりも速やかにシングルの場所でのご通知を選択するフィルタ。

あなたはHICPPか似たようなものをフォローしていると思います。

私たちがしていることは、コードがQACPPに違反し、それが誤っていると思う場合、Doxygen(AddTogroupコマンドを介してそれらのリストを簡単に取得する)を介してそれをメモし、理由を与えて、なぜ違反しているのかを示してから警告を無効にします経由 //PRQA 指図。

これらは、このオブジェクトの状態を変更しないため、通常、システム全体の状態を変更しても、技術的にはconstメソッドにすることができます。特に、リスナーオブジェクトはこのオブジェクトに呼び戻して変更する場合があります。

リスナーは状態を変更できるため、この方法はconstであってはなりません。あなたが書いたものから、あなたは多くのconst_castを使用してポインターを通して電話をかけているように聞こえます。

const正確性には、(意図的に望ましい)伝播方法があります。 constをどこでも逃れることができる場所を使用する必要がありますが、const_castとc-style-castsはクライアントコードを扱うアーティファクトである必要があります。コードでは決してありませんが、非常にまれな例外です。

もしも void NotifyFooUpdated(); 電話 listeners[all].OnFooUpdated() オンの間 OnFooUpdated() constではないので、この突然変異を明示的に適格にする必要があります。あなたのコードが全体を通して正しい場合(私が質問しています)、それを(メソッド宣言/リスナーアクセスを介して)リスナー(メンバー)を変えていることを明示的にします。 NotifyFooUpdated() コンスト以外の資格を取得する必要があります。そのため、突然変異を可能な限りソースに近いと宣言するだけで、チェックアウトし、Constorectnessが適切に伝播します。

仮想関数constを作成することは、常に難しい決定です。それらを非コンストすることは簡単な方法です。リスナー関数は、多くの場合、リスニングの側面を変更しない場合(このオブジェクトの場合)constである必要があります。イベントを聴くと、リスニングパーティが(一般的なケースとして)Unregister自体を登録する場合、この関数は非コンストである必要があります。

オブジェクトの内部状態は、フーチャングされた呼び出しで変更される場合がありますが、インターフェイスのレベルでは、次回のオンフーチェンジが呼び出されると同様の結果が得られます。それはそれをconstにします。

クラスでconstを使用する場合、そのクラスのユーザーがクラスがデータとどのように対話するかを知っているのを支援します。あなたは契約を結んでいます。 constオブジェクトへの参照がある場合、そのオブジェクトで行われた呼び出しが状態を変更しないことがわかります。そのリファレンスのコンストネスは、まだ発信者との契約にすぎません。オブジェクトは、可変変数を使用してバックグラウンドでいくつかの非コンストアクションを自由に行うことができます。これは、キャッシュ情報をキャッシュする場合に特に役立ちます。

たとえば、メソッドのクラスを使用できます。

int expensiveOperation() const
{
    if (!mPerformedFetch)
    {
        mValueCache = fetchExpensiveValue();
        mPerformedFetch = true;
    }
    return mValueCache;
}

この方法は初めて実行するのに長い時間がかかる場合がありますが、その後の呼び出しの結果をキャッシュします。ヘッダーファイルが変数を実行した変数とValueCacheが可変であると宣言することを確認する必要があります。

class X
{
public:
    int expensiveOperation() const;
private:
    int fetchExpensiveValue() const;

    mutable bool mPerformedFetch;
    mutable int mValueCache;
};

これにより、constオブジェクトが発信者と契約を結び、バックグラウンドで少し賢く作業しながらconstのように動作します。

私はあなたのクラスにリスナーのリストを可変性として宣言させることをお勧めし、他のすべてを可能な限りconstにすることをお勧めします。オブジェクトの発信者に関する限り、オブジェクトはまだconstであり、そのように動作します。

constは、オブジェクトの状態がメンバー関数によって変更されないことを意味します, 、これ以上、それ以下。副作用とは何の関係もありません。したがって、私があなたのケースを正しく理解している場合、オブジェクトの状態が変更されないため、関数はconstと宣言する必要があります。アプリケーションの他の部分の状態は、このオブジェクトとは何の関係もありません。オブジェクト状態にオブジェクトの論理状態の一部ではない非コンストサブオブジェクト(ミューテックスなど)がある場合でも、関数をconstを作成する必要があり、それらの部分は変異できると宣言する必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top