2

C++ では、いくつかの基本クラス (Base など) 内に仮想関数がある場合、この仮想関数をオーバーライドしたい場合、この仮想関数を再度宣言して、派生クラスでもコンパイルできるようにする必要があります。

class Base {
public:
    virtual void virtualFunction();
    static int s_whatSoEver[];
private:
    void _privateFunction();
}
class Derived {
public:
    virtual void virtualFunction();
}

仮想関数プロトタイプを変更したい場合は、派生物のすべての宣言を変更する必要があるため、これはばかげていませんか?

また、ヘッダー ファイルはパブリック インターフェイスの定義に使用され、このインターフェイスを使用するユーザーはそれらをまったく気にする必要がないため、ヘッダー ファイル内で保護された関数またはプライベート関数を宣言する必要があるのはなぜですか? おそらく、Objective-C と同じように、.cpp ファイルでプライベートまたは保護された関数を直接実装して宣言することができます。

C++ には静的初期化子もありません。静的クラス変数を初期化したい場合は、このためのクラスを作成する必要があります。

class BaseStaticVariableInitializer {
public:
    BaseStaticVariableInitializer() {
        Base::s_whatSoEver = new int[20];
        for (int i = 0; i < 20; i++) {
            s_whatSoEver[i] = xxx;
        }
    }
    ~BaseStaticVariableInitializer() {
         delete [] Base::s_whatSoEver;
    }
}

具体的には、静的クラス定数を初期化します。

static BaseStaticVariableInitializer s_baseStaticVariableInitializer;

無知で申し訳ありませんが、DRY に適合するように C++ コードを記述する正しい方法は何ですか?

4

4 に答える 4

6

仮想関数プロトタイプを変更したい場合は、派生物のすべての宣言を変更する必要があるため、これはばかげていませんか?

いいえ。基本クラスで仮想関数プロトタイプを変更している場合は、パブリック インターフェイスを変更しています。あなたはそれをすべきではありません。

また、ヘッダー ファイルはパブリック インターフェイスの定義に使用され、このインターフェイスを使用するユーザーはそれらをまったく気にする必要がないため、ヘッダー ファイル内で保護された関数またはプライベート関数を宣言する必要があるのはなぜですか?

protectedメンバーは、クラスのパブリック インターフェイスの一部と見なす必要があります。は、そうしなければ危険にさらされるエラーを回避するのprotectedに役立ちますpublic。ただし、間違いはありません。protectedメンバーはクラスのインターフェイスの一部であり、そのように扱う必要があります。

ヘッダー ファイルの sについてprivate: はい、同意します。多くの点で、それらを実装ファイルのみに保持する方がより論理的です。ただし、クラスを値で渡す場合を考慮してください。

foo(Bacon b)
{
    b.cook();
}

を呼び出すには、完全なクラス定義をコンパイラで使用できるようにfoo()する必要があります。Bacon(注: メンバ関数の定義ではなく、クラス定義のみです。)これは、コンパイラが を呼び出すときにクラスに割り当てるスタック領域を知ることができるようにするためfoo()です。コンパイラが変数を探すために実装ファイルも検索する必要がある場合private、解析はより複雑になります (そして、コンパイルはおそらくさらに遅くなります)。

アップデート

あなたがDRYについて言及したので、私はこれを指摘しなければなりません。DRY 原則は次のように述べています。

知識のすべての部分は、システム内で単一の明確で信頼できる表現を持っている必要があります。

関連するクラスで仮想関数を宣言しても、この原則に違反しません。それらは同じ機能ではありません。ではBase、あなたはそれが であると述べていBase::fooますvirtual。では、も であるDerivedと述べています。とは 2 つの別個の関数ですが、ポインタまたは への参照を介して両方を呼び出すことができるのはたまたまです。Derived::foovirtualBase::fooDerived::fooBase

于 2013-07-23T02:10:55.080 に答える
1

簡単な短い答え。1]最初の質問については、C ++でのオーバーライドとオーバーロードの違いを参照してください2]静的メンバー関数で実行できる静的memebrを初期化するには

class Base {
public:
  virtual void virtualFunction();
  static int s_whatSoEver[];

  static void BaseStaticVariableInitializer() {
    Base::s_whatSoEver = new int[20];
    for (int i = 0; i < 20; i++) {
        s_whatSoEver[i] = xxx;
    }
}
private:
 void _privateFunction();

これを.cppファイルで個別に定義します

 static int Base::s_whatSoEver[20];
于 2013-07-23T02:13:09.310 に答える
1

ヘッダー ファイル内で保護された関数またはプライベート関数を宣言する必要があるのはなぜですか? ...

DRY に適合するように C++ コードを記述する正しい方法は何ですか?`

Pimpl 慣用句を使用して、ヘッダー ファイルから実装の詳細 (プライベート メンバーとメソッド シグネチャの宣言) を隠すことができます。さらに、ビルドが高速化されます。Qt はこのイディオムを広く使用しています。

于 2013-07-23T10:55:37.000 に答える