본문 바로가기

Programming/C&CPP

함수 오버로딩(overloading)과 오버라이딩(overriding)

반응형

C++을 배우면서 이 단어들을 들어 보지 못한 사람은 아마 없을 것입니다.

단어가 비슷하기 때문에 처음 배우면 개념이 상당히 헷갈리기도 합니다.

간단하게 오버로딩과 오버라이딩을 정의해보면 다음과 같습니다.

오버로딩은 함수의 중복 정의, 오버라이딩은 함수의 재정의

1. 오버로딩(Overloading)

오버로딩은 다음과 같습니다.

#include <iostream>
using namespace std;

void func(int i)
{
	cout << "func(int) is called." << endl ;
}

void func(char c)
{
	cout << "func(char) is called." << endl;
}

void func(int i, int j)
{
	cout << "func(int, int) is called." << endl;
}

/*
int func(int i)
{
	cout << "int func(int) is called." << endl;
}
*/

int main()
{
	func(3);
	func('a');
	func(1, 2);
}

오버로딩을 자세히 정의해 보면 다음과 같습니다.

오버로딩은 함수명이 같고 매개 변수의 타입이나 개수가 다른 함수를 허용하는 것이다.

즉, 함수명이 같이도 전달받는 인자의 개수나 타입이 다르면 서로 다른 함수로 인식합니다.

위의 결과를 보면 분명히 그렇게 출력되고 있음을 알 수 있습니다.

만약 저 소스에서 주석처리된 부분을 풀어주면 어떻게 될까요?

아마 다음과 같은 오류 코드들(VC++ 6.0 기준)을 뱉어낼 것입니다.

주석이 풀린 곳의 함수명에서 다음과 같은 오류가 발생하게 됩니다.

error C2556: 'int func(int)' : overloaded function differs only by return type from 'void func(int)'

'func' : redefinition; different basic types

번역해 보면 오버로딩이 리턴값만 바뀐 걸로 되었다고 하며 재정의 되어 있다고 나옵니다.

그리고 호출하는 부분(func(1))에서는 다음과 같은 오류가 발생합니다.

error C2264: 'func' : error in function definition or declaration; function not called

이것이 의미하는 바는 무엇일까요?

바로 오버로딩은 리턴타입이 다른 것만으로는 허용되지 않는다는 것입니다.

void func(int a) int func(int a)와 같은 형식은 오버로딩이 아니라는 것입니다.

이것으로 오버로딩의 정의를 확실히 알 수 있을 것입니다.

오버로딩을 활용하는 방법에는 연산자 오버로딩 등의 특수한 방법도 존재합니다.

연산자 오버로딩은 기본 형식만 허용하는 연산자를 클래스 등의 사용자 정의 타입에도 적용시키는 것입니다.

간단한 예를 하나 들자면 C++에서는 복소수의 사칙연산을 지원하지 않는데

사칙 연산자가 우리가 만든 복소수 클래스를 지원하게 해주는 것입니다.

2. 오버라이딩(Overriding)

오버라이딩은 이미 이전 글인 상속&다형성 파트에서 언급되어져 있습니다.

오버라이딩은 함수의 재정의라고 위에 언급했는데, 상속에서의 중요한 기능 중 하나입니다.

자식 클래스는 부모 클래스의 private 속성에 있는 부분을 제외하고는 모두 상속 받습니다.

그런데 부모의 기능을 자동으로 상속받지만 좀 더 구체화된 자식 클래스는

새로운 기능을 더하고도 싶고, 부모가 하는 것과는 다른 기능을 하고 싶기도 합니다.

다음의 소스의 결과값은 어떻게 될까요?
#include <iostream>
using namespace std;

class Base
{
public:
	void func()
	{
		cout << "B::func() is called" << endl;
	}
};

class Derived : public Base
{
};

int main()
{
	Base b;
	Derived d;

	b.func();
	d.func();
}

다음과 같은 출력값을 보여줄 것입니다.

즉, 부모에게 상속받은 것은 그냥 바로 사용이 가능한 것입니다.

Derived에는 직접적으로 func() 함수가 정의되지 않았지만 부모의 함수를 사용할 수가 있습니다.

오버라이딩은 함수를 자식 클래스가 재정의할 수 있게 해주는 기능 입니다.

override의 단어의 의미는 '무시하다, 거절하다, 무효로 하다, 뒤엎다' 등 입니다.

overriding의 의미가 확 와닿을 것입니다.

다음과 같은 소스를 보도록 하겠습니다.

#include <iostream>
using namespace std;

class Base
{
public:
	void func()
	{
		cout << "B::func() is called" << endl;
	}
};

class Derived : public Base
{ 
public:
	void func()
	{
		cout << "D::func() is called" << endl;
	}
};

int main()
{
	Base b;
	Derived d;

	b.func();
	d.func();
}

상속을 받은 Derived 클래스에서 func() 함수를 오버라이드하였습니다.

정상적으로 호출이 되는 것이 확인됩니다.

이전 포스팅에서 다형성을 이용하는데 가상 함수(Virtual Function)을 사용한다는 것을 확인했습니다.

2014/12/03 - [Programming/C&C++] - 다형성과 가상함수

순수 가상 함수는 상속 시에 반드시 재정의를 하도록 강제할 수 있습니다.

오버라이딩을 사용할 때 부모의 기능에 추가적인 기능을 사용하고 싶은 경우도 있을 것입니다.

그럴 때는 부모클래스::함수() 형태로 재정의한 함수에 넣어주면 됩니다.

예제의 Derived 클래스의 func 안에 Base::func() 형태로 필요한 위치에서 호출을 해주면 됩니다.

함수의 오버라이딩과 오버로딩을 헷갈리지 않고 개념을 이해하시기 바랍니다.

반응형