質問

私はStroustrupによるC ++ 0x FAQを読んでいて、このコードで動けなくなりました。次のコードを検討してください

struct A
{
    void f(double)
    {
        std::cout << "in double" << std::endl;
    }
};

struct B : A
{
    void f(int)
    {
        std::cout << "in int" << std::endl;
    }
};


int main()
{
    A a; a.f(10.10);  // as expected, A.f will get called
    B b; b.f(10.10);  // This calls b.f and we lose the .10 here
    return 0;
}

私の理解では、型が継承されると、すべての保護されたメンバーとパブリックメンバーが派生クラスからアクセス可能になります。しかし、この例によると、私は間違っているようです。 b.f が基本クラス f を呼び出すことを期待していました。派生クラスを次のように変更することで、期待どおりの結果が得られました

struct B : A
{
    using A::f;
    void f(int)
    {
        std::cout << "in int" << std::endl;
    }
};

質問

  1. 最初のコードでなぜ機能しなかったのですか?
  2. C ++標準のどのセクションでこれらのスコープルールがすべて説明されていますか?
役に立ちましたか?

解決

最初のコードは、c ++が機能するように設計されているため機能します。

オーバーロード解決は、非常に複雑な一連のルールに従います。 Stroustrupのc ++聖書15.2.2から&quot; [A]異なる基本クラスの関数間の曖昧性は、引数の型に基づいて解決されません。

彼は、「使用」の使用法を説明し続けています。あなたが説明したように。

これは言語の設計上の決定でした。

私は標準ではなくStroustrupの本をフォローする傾向がありますが、間違いなくそこにあると確信しています。

[編集]

ここにあります(標準から):

第13章

同じスコープ内の単一の名前に対して2つ以上の異なる宣言が指定されている場合、その名前は オーバーロード。

そして:

13.2宣言の一致

1同じスコープ内にあり、同等のパラメーター宣言(13.1)を持っている場合、同じ名前の2つの関数宣言は同じ関数を参照します。派生クラスの関数メンバーは、次の関数メンバーと同じスコープ内にありません 基本クラスの同じ名前。

他のヒント

A :: fが「隠されている」ためです。 「オーバーロード」ではなくまたは「オーバーライド」。参照:

http://www.parashift.com /c++-faq-lite/strange-inheritance.html#faq-23.9

オーバーロード解像度を検索します。 類似しているが同一ではない質問

C ++では、スコープ全体にオーバーロードはありません。派生クラスのスコープは例外ではありません。 (C ++プログラミング言語による)

詳細については、 http://www.researchをご覧ください。 att.com/~bs/bs_faq2.html#overloadderived

最初の場合、基本クラスメソッド 'f'は、派生クラスメソッドによって非表示になります。 C ++では、スコープ全体にオーバーロードはありません。それが呼び出されない理由です。 C ++標準では、 セクション10.2メンバー名ルックアップ[class.member.lookup] のすべてのメンバー名ルックアップルールについて説明しています。 HTH

コードの最初のバージョンでは、実際にB :: fを呼び出す必要があります。シンボル&quot; f&quot;を再定義します。構造体&quot; B&quot;で、元のシンボル&quot; f&quot;を非表示にします。構造体「A」から。一見過負荷ではありません。

コンパイラがb.f()に出会うたびに、&quot; B&quot;を検索します。シンボル&quot; f&quot;の構造体。そこに存在するため、コンパイラーはB :: f(int)を呼び出して、doubleをintに変換することを決定します。より適切な関数を見つけるために親クラスをスキャンする必要はありません...

まだ、「A :: f」を使用して&quot;を追加すると、コンパイラがシンボル&quot; fの親クラスをスキャンするための明示的なディレクティブになります。現在、Bクラスには、intとdoubleの2つのオーバーロード関数があります。

また、&quot; using&quot;を使用せずにb.A :: f()を書くことができると信じています。元の例のディレクティブ...

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