3

そこで最近、見たことのない特定のテクニック (イディオム?) を使用したソース コードを見つけました。簡単に言えば; 問題のクラスに静的変数を使用する代わりに、クラスのソース ファイル内でローカル変数を使用していました。

myclass.h

class myclass {
    //static int myint;

public:
    myclass();
    ~myclass();
    int count();
};

myclass.cpp

#include "myclass.h"

int myint = 0;

myclass::myclass() {
    myint++;
}
myclass::~myclass() {
    myint--;
}

int myclass::count() {
    return myint;
}

main.cpp

#include "myclass.h"
#include <iostream>

int main() {
    myclass aclass;
    myclass theclass;

    std::cout << theclass.count(); //outputs 2
    return 0;
}

私の質問は、なぜ誰かが静的変数を使用してこのアプローチを採用するのでしょうか?

私の見解では、理想的には、変数は myclass クラス (private static) だけが認識し、継承はまったく重要ではないため (この場合)、他の人がこの変数について知ることができなくなる可能性があります。しかし、それが私が見ることができる唯一の利点です。それがそれを正当化するかどうかはわかりません。

プライベートな (静的/非静的) メンバー関数についても同じことが言えます。継承が重要でない場合。

EDIT:周りを読んだ後、一部の人々がまだCプログラミングスタイルを使用しているためだと突き刺します...

4

3 に答える 3

7

静的メンバー変数を使用するか、グローバル変数を使用するか、ローカルで宣言された静的変数を使用するかは、実際には重要ではありません。唯一重要なことは、オブジェクトには静的な保存期間が必要であるということです。それを超えて、選択は主に個人的な好みまたはコーディングスタイルのガイドラインに基づいています。

残念ながら、このコードは基本的に間違っています。は「非表示」であり、 myclass.cppmyint内からのみ直接アクセスできますが、外部リンクがあります。これは、他の翻訳ユニットから(他の翻訳ユニットで使用することにより)アクセス可能でextern int myintあり、その定義がmyint他の翻訳ユニットの他の定義と競合する可能性があることを意味します。

これを修正するには、宣言するstatic(内部リンケージを与える)か、できれば名前のない名前空間で宣言する必要があります。

namespace {
    int myint;
}

(名前のない名前空間内のオブジェクトはまだ外部リンケージを持っている可能性がありますが、一意の名前が付けられているため、コンパイルされたトランスレーションユニットの外部からその名前で使用することはできません。)

于 2011-02-12T08:45:41.497 に答える
3

あなたの例では、変数は静的ではなく、適切に宣言されていればコンパイル単位の外で技術的に可視です。これが意図的でない場合、別のコンパイルユニットが同じ名前の変数に対して同じトリックを使用すると、問題の原因になる可能性があります (これを修正するには、James McNellis の回答を参照してください)。

適切に宣言された static を想定すると (たとえば、名前のない名前空間アプローチを使用する)、この手法はクラスのユーザーから変数を完全に隠すため、クラスの static よりも優れている可能性があります。つまり、その変数を追加または変更する必要がある場合、クライアントを再コンパイルする必要さえありません (実装 .cpp ファイルを再コンパイルしてから、プログラムを再リンクするだけで済みます)。クラスが大きなプロジェクトのあらゆる場所で使用されている場合、これは大きな違いになる可能性があります (内部の詳細が変更されたため、全世界を再コンパイルするのではなく、1 つのファイルだけをコンパイルします)。

また、静的変数がintより複雑なもの (テンプレート化されたクラス インスタンスなど) である場合、変数を静的としてクラスに配置すると、より多くのデータをクライアントに公開する必要があり、不要な依存関係が導入されます。

この望ましくない依存関係の問題は非常に重要であると考えられるため、「コンパイラ ファイアウォール」イディオムの実装を見つけることができます。この隠蔽は、それの部分的で軽いバージョンのようなものです。

于 2011-02-12T09:05:25.707 に答える
1

私の質問は、なぜ誰かが静的変数を使用してこのアプローチを採用するのでしょうか?

非表示にするものがあれば意味があります。通常、int は非表示にする価値はありませんが、大きなライブラリは非表示にする必要があります。作成者は、実装の詳細をクライアントから隠したい場合もあります。

静的関数に関しては、通常、それらが単なる無料のヘルパーであり、実際には属していないか、クラス インターフェイスの一部である必要がある場合は非表示にします。

一般的には、単に組織的な目的でクラス インターフェイスに配置します。

于 2011-02-12T09:05:46.963 に答える