[cpp] 오버로딩된 가상 함수 숨김 문제

@codemaru · December 12, 2023 · 2 min read

다음과 같은 간단한 코드에서 시작해 보자. 순수 가상 클래스인 Base에 Bark란 메소드가 있고, 그걸 상속 받은 순수 가상 클래스인 Derived는 BarkN을 가지고 있다. 이를 상속 받은 Dog은 두 메소드를 구현한다. main에서는 Dog를 할당해서 Derived 포인터를 통해서 Bark와 BarkN을 호출하고 있다. 아무 문제 없는 코드다.

#include <stdio.h>

class Base
{
public:
	virtual void Bark() = 0;
};

class Derived : public Base
{
public:
	virtual void BarkN(int n) = 0;
};

class Dog : public Derived
{
public:
	virtual void Bark() { printf("Dog Bark\n");
	}

	virtual void BarkN(int n)
	{
		for (int i = 0; i < n; ++i)
			printf("Dog Bark\n");
	}
	
};

int
main()
{
	Derived *dog = new Dog;
	dog->Bark();
	dog->BarkN(5);
}

우리는 C++에서 함수를 오버로딩할 수 있다는 것을 알고 있다. 그래서 굳이 BarkN으로 이름을 지을 필요가 없다는 것을 깨달았다. N을 제거하고 다음처럼 Bark로 코드를 고쳐보자. 이제는 컴파일이 되지 않는다. dog->Bark(); 호출하는 부분에서 그런 함수를 찾을 수 없다고 오류가 발생하는 것이다. 이는 상속 받은 클래스에서 함수를 오버로딩하면 상위 클래스의 메소드가 숨겨지는 문제 때문이다.

#include <stdio.h>

class Base
{
public:
	virtual void Bark() = 0;
};

class Derived : public Base
{
public:
	virtual void Bark(int n) = 0;
};

class Dog : public Derived
{
public:
	virtual void Bark() { printf("Dog Bark\n");
	}

	virtual void Bark(int n)
	{
		for (int i = 0; i < n; ++i)
			printf("Dog Bark\n");
	}
	
};

int
main()
{
	Derived *dog = new Dog;
	dog->Bark();
	dog->Bark(5);
}

문제를 해결하기 위해서는 아래 코드처럼 Derived 클래스에서 상위 클래스의 메소드를 사용하겠다는 것을 명시적으로 표시해주면 된다.

class Derived : public Base
{
public:
	using Base::Bark;
	virtual void Bark(int n) = 0;
};
@codemaru
돌아보니 좋은 날도 있었고, 나쁜 날도 있었다. 그런 나의 모든 소소한 일상과 배움을 기록한다. 여기에 기록된 모든 내용은 한 개인의 관점이고 의견이다. 내가 속한 조직과는 1도 상관이 없다.
(C) 2001 YoungJin Shin, 0일째 운영 중