基底クラスおよび派生クラスからのメンバー関数の多重定義

C++クラス Af と名付けられたメンバー関数は、 戻りの型や引き数に関係なく、A の基底クラスで、他の f という名前のメンバーをすべて隠します。 次の例は、このことを示しています。

struct A {
  void f() { }
};
 
struct B : A {
  void f(int) { }
};
 
int main() {
  B obj_B;
  obj_B.f(3);
//  obj_B.f();
}

コンパイラーは、void B::f(int) の宣言が A::f() を隠しているので、 関数呼び出し obj_B.f() を許可しません。

基底クラス A の関数を、派生クラス B で、 隠蔽ではなく多重定義するには、using 宣言を使用して、 関数の名前を B のスコープに導入します。 以下の例は、using 宣言 using A::f を除いては、直前の例と同じです。

struct A {
  void f() { }
};
 
struct B : A {
  using A::f;
  void f(int) { }
};
 
int main() {
  B obj_B;
  obj_B.f(3);
  obj_B.f();
}

クラス Busing 宣言があるので、 名前 f は 2 つの関数で多重定義されます。 これで、コンパイラーは、関数呼び出し obj_B.f() を許可します。

同じ方法で仮想関数を多重定義できます。 次の例は、このことを示しています。

#include <iostream>
using namespace std;
 
struct A {
  virtual void f() { cout << "void A::f()" << endl; }
  virtual void f(int) { cout << "void A::f(int)" << endl; }
};
 
struct B : A {
  using A::f;
  void f(int) { cout << "void B::f(int)" << endl; }
};
 
int main() {
  B obj_B;
  B* pb = &obj_B;
  pb->f(3);
  pb->f();
}

次に、上記の例の出力を示します。

void B::f(int)
void A::f()

関数 f を、using 宣言を指定して、基底クラス A から派生クラス B に導入し、さらに A::f として同じパラメーター型を持つ B::f という名前の関数が存在するとします。 関数 B::f は、関数 A::f と競合するというより、むしろそれを隠蔽します。 次の例は、このことを示しています。

#include <iostream>
using namespace std;
 
struct A {
  void f() { }
  void f(int) { cout << "void A::f(int)" << endl; }
};
 
struct B : A {
  using A::f;
  void f(int) { cout << "void B::f(int)" << endl; }
};
 
int main() {
  B obj_B;
  obj_B.f(3);
}

次に、上記の例の出力を示します。

void B::f(int)
 

関連参照

IBM Copyright 2003