7

using最近、このキーワードの新しい用途を発見しました。機能を参照するのではnamespaceなく、派生クラスの宣言内で。私の場合、これは「operator=」メンバー関数を取り巻く問題に関して適切でした。

宣言を考えると、次のような状況がありました。

class CString{
public:
    ...//Various functions.
    operator=(const CString &cString)
    {
        //code to share internal array and increment reference count
    }
    operator=(const wchar_t *pstrString)
    {
        //code to create a personal internal array,
        //resize it appropriately and copy the pstrString argument.
    }
    ...
};

class CStringEx : public CString{
    ...//various members that expand upon CString's abilities.
};

... のオブジェクトがCStringEx期待どおりに機能しませんでした:

CStringEx cString;

cString=L"String contents";

代わりに、' CStringEx has no 'operator=()' function that takes an argument of type wchar_t* ' (または - 非常に近い - その効果に近い言葉)というコンパイラ エラーが生成されました。かなりの研究の後、これはoperator=、派生クラスのコンパイラによって自動的に生成されたメンバー関数でさえ、その親クラスから継承されたものをオーバーライドするためであることがわかりました。これは私には直観に反し、ユーザーフレンドリーに思えます

ただし、usingキーワードを追加すると:

class CStringEx : public CString{
public:
    using CString::operator=;
    ...
};

...子クラス親のoperator=メンバー関数を使用するようになり、すべて問題ありません。

ここまでは順調ですね。ただし、ここや他の場所をさらに読んだ後、多くのプログラマーがusingこの目的での使用を好まないことがわかりました。たとえば、親からすべての operator= を取り込むなど、望ましくない可能性のある副作用について説明しているコメンテーターを読みました。ただし、非常に特殊な状況を除いて、すべての親メンバー関数を継承する理由がわかりません。これが主な懸念事項である場合、誰かがそうすることの一般的な危険性を説明できますか?

私が考えることができる唯一の代替手段は、その親のすべて のメンバー関数の子クラスにスタブ関数を書き出してから、operator=それらのそれぞれのメンバー関数を明示的に呼び出すことです。

class CStringEx : public CString{
public:
    ...
    const CStringEx& operator=(const wchar_t* pstrString)
    {
        CString::operator=(pstrString);
        return *this;
    }
    const CStringEx& operator=(const CString &cString)
    {
        CString::operator=(cString);
        return *this;
    }
    ...//and so on...
};

このバージョンと比較すると、using CString::operator=これは非常に醜く、扱いにくく、面倒です。using繰り返しになりますが、キーワードを使用しないのはなぜですか?

4

1 に答える 1

1

これは少し主観的なので、私たちが知っていることを確認しましょう。

が仕事に適したツールである場合usingは、それを使用する必要があります。それは言った:

  • using意図せずに新しく追加されたものであっても、常にすべての親メソッド/演算子が取り込まれますこれにより、誰かが子オブジェクトとうまく相互作用しない親代入演算子を作成すると、コードが壊れる可能性さえあります。
  • 親のコピー代入演算子を導入するということは、 aCStringExから aを作成できることを意味しますがCString、おそらくこれは意図された動作です。
  • 将来の読者/メンテナは、構文を使用する演算子に慣れていない可能性があり、コードを理解するのが少し難しくなる可能性があります。

(聞いたことに基づいて) 最初に疑問を呈しているという事実と上記の点を考慮して、一歩下がって設計を見てみましょう。には次のCStringEx2 つの可能性があります。

  1. 追加のデータ メンバーがあります。この場合、代入では子クラスのメンバーが処理されないため、親演算子を継承すると、一部またはすべてのケースで何らかの問題が発生することを断言します。
  2. 追加のデータ メンバーはなく、追加のコード機能を提供するだけです。この場合、子クラスを使用しないでください。代わりに、(反復子) 範囲、または必要に応じてCStringオブジェクトのいずれかで動作する自由関数アルゴリズムを記述します。
于 2014-10-30T18:53:08.613 に答える