오버로드 된 가상 함수를 다시 선언해야하는 이유는 무엇입니까?

Nov 26 2020

두 개의 오버로드 된 함수 f(void)f(int). 클래스 Derived구현 f(int)호출하여 f(void). Derived2구현 f(void)합니다.

컴파일러 Derived::f(int)는 호출을 원하기 때문에 구현을 거부 f(int)하지만 을 호출하고 싶어서 인수를 제공하지 않았습니다 f(void). 컴파일러가이를 거부하는 이유는 무엇입니까? 줄을 추가하면 virtual int f(void) = 0;문제가 해결 되는 이유는 무엇 입니까?

class Base
{
public:
  explicit Base(void) {}
  virtual ~Base(void) {}

  virtual int f(void) = 0;
  virtual int f(int i) = 0;
};

class Derived : public Base
{
public:
  // provide implementation for f(int) which uses f(void). Does not compile.
  virtual int f(int i) {puts("Derived::f(int)"); return f();}
  // code only compiles by adding the following line.
  virtual int f(void) = 0;
};

class Derived2 : public Derived
{
public:
  // overwrite only f(void). f(int) is implemented by Derived.
  virtual int f(void) {puts("Derived2::f(void)"); return 4;}
};

int main(void)
{
  Base * p = new Derived2();
  int i0 = p->f();  // outputs Derived2::f(void) and returns 4
  int i1 = p->f(1); // outputs "Derived::f(int) Derived2::f(void)" and return 4
  delete p;
  return 0;
}

답변

5 songyuanyao Nov 26 2020 at 08:18

Derived::fBase::fs를 숨 깁니다 . 주어 return f();의 본문에 Derived::f(int)이름이 f범위에서 발견 Derived한 후, 조회 이름 정지. 의 이름을 Base찾을 수 없으며 과부하 해결에 참여합니다.

이름 조회는 모든 종류의 선언을 하나 이상 찾을 때까지 아래에 설명 된대로 범위를 검사합니다. 이때 조회가 중지되고 더 이상 범위는 검사되지 않습니다.

의 범위에 using Base::f;이름을 소개하기 위해 추가 할 수 있습니다 .BaseDerived

class Derived : public Base
{
public:
  using Base::f;

  // provide implementation for f(int) which uses f(void).
  virtual int f(int i) {puts("Derived::f(int)"); return f();}
};