次のコードを検討してください。
struct A
{
void f()
{
}
};
struct B1 : A
{
};
struct B2 : A
{
};
struct C : B1, B2
{
void f() // works
{
B1::f();
}
//using B1::f; // does not work
//using B1::A::f; // does not work as well
};
int main()
{
C c;
c.f();
return 0;
}
ダイヤモンド問題を解決する方法に関する標準的な回答 (「仮想継承を使用する」) をコピーして貼り付けないでください。ここで私が尋ねているのは、この場合に using 宣言が機能しない理由です。正確なコンパイラ エラーは次のとおりです。
In function 'int main()':
prog.cpp:31:6: error: 'A' is an ambiguous base of 'C'
c.f();
次の例から、using 宣言が機能するはずだという印象を受けました。
struct A
{
void f()
{
}
};
struct B
{
void f()
{
}
};
struct C : A, B
{
using A::f;
};
int main()
{
C c;
c.f(); // will call A::f
return 0;
}
ベストアンサー1
標準的な引用文は他の人が見つけることもできますが、私は概念的に説明します。
それは機能しない。使用宣言 名前の検索にのみ影響します。
あなたの使用宣言通常は失敗する名前検索を成功させる。つまり、コンパイラに関数はどこにありますかf
。しかし、それは語られていないどのA
サブオブジェクトf
が作用するかつまり、が呼び出されたthis
ときに暗黙のパラメータとして渡されるものを指定しますf
。
のサブオブジェクトA::f
が2つあるにもかかわらず、関数は1つしか存在せず、暗黙的に型の引数を取ります。オブジェクトでそれを呼び出すには、を暗黙的に に変換する必要があります。これは常に曖昧であり、いかなる影響も受けません。A
C
this
A*
C
C*
A*
使用宣言。
(データ メンバーを 内に配置すると、より意味をなしますA
。 すると、には、C
このようなデータ メンバーがそれぞれ 2 つずつ含まれることになります。が呼び出され、データ メンバーにアクセスする場合、から継承されたサブオブジェクトf
内のデータ メンバーにアクセスするのでしょうか、それともから継承されたサブオブジェクト内のデータ メンバーにアクセスするのでしょうか。)A
B1
A
B2