본문 바로가기

Programming/CPP11&14

[C++11] final과 override

반응형

C++에서는 명시적으로 클래스의 상속을 막는 방법이 없었습니다.

C++ CLI 등에서 selaed라는 키워드가 존재했지만 이것은 표준이 아닌 MS 확장 키워드입니다.

C# 역시 sealed라는 키워드를 사용합니다.

C#의 sealed 키워드에 대한 내용은 다음 링크에서 확인 가능합니다.

2014/12/27 - [Programming/C#] - sealed 키워드를 사용한 클래스 상속 방지

C++ CLI나 C#이나 모두 닷넷을 지원하기 위해서 만들어진 것을 생각하면 공통된 특정 키워드가 있는 것이 이해가 갑니다.

C++11에서는 상속을 정교하게 다루기 위해 final과 override라는 새로운 키워드가 추가되었습니다.

final은 상속을 차단하기 위해 추가된 키워드이고,

override는 클래스의 메소드를 명시적으로 오버라이딩하기 위해 추가된 키워드입니다.

먼저 예제를 보도록 하겠습니다.

class Base
{
public:
	Base();
	virtual int func(int nVal);
};

class Derived : public Base
{
public:
	Derived();
	virtual int func(float nVal);
};

Base 클래스와 Derived 클래스에 func라는 메소드가 존재합니다.

약 func를 override하고 싶었는데 파라미터를 int에서 float로 바꾸는 실수를 했다고 가정합니다.

이런 경우 컴파일러는 이것을 오류나 경고로 처리해 주지 않습니다.

사용자의 의도와는 다르지만 문법적으로는 아무 문제가 없기 때문입니다.

이것을 막아주고 오버라이드한다는 것을 명시적으로 해주는 것이 바로 override입니다.

실제 사용 예제를 확인해 보도록 하겠습니다.

class Base
{
public:
	Base();
	virtual int func(int nVal);
	int funcNormal(int nVal);
};

class Derived : public Base
{
public:
	Derived();
	// virtual int func(float nVal) override;
	// error C3668: 'Derived::func' : method with override specifier 'override' did not override any base class methods

	virtual int func(int nVal) override;

	// int funcNormal(int nVal) override;
	// error C3668: 'Derived::funcNormal' : method with override specifier 'override'
	// did not override any base class methods
};

2가지 에러 상황을 주석 처리 하였습니다.

첫 번째 에러의 내용은 Base에 없는 메소드를 오버라이드하려고 한다는 내용입니다.

override 키워드를 사용하면 위와 같은 실수를 막을 수 있게 됩니다.

두 번째 에러는 virtual이 아닌 함수를 override로 처리했을 때 발생하는 문제입니다.

override는 virtual 메소드에만 적용이 가능합니다.

굳이 불편함을 감수하고서 override를 사용하는 이유는 간단합니다.

사람이 할 수 있는 실수를 컴파일러가 다룰 수 있게 하자입니다.

final 키워드는 상속을 방지하는 키워드입니다.

클래스에도 사용이 가능하고, 클래스의 메소드에도 가능합니다.

class Base1 final
{
public:
	Base1();
};

// error C3246: 'Derived1' : cannot inherit from 'Base1' as it has been declared as 'final'
// class Derived1 : public Base1
// {
// };

class Base2
{
public:
	Base2();
	virtual int func() final;
};

class Derived2 : public Base2
{
public:
	Derived2();
	// error C3248: 'Base2::func': function declared as 'final' cannot be overridden by 'Derived2::func'
	// virtual int func();
};

첫 번째 주석 부분은 final로 선언된 클래스 Base1을 상속받으려고 하기 때문에 에러가 발생하게 됩니다.

두 번째 주석 부분은 final로 선언된 메소드를 오버라이드하려고 하기 때문에 발생합니다.

override 키워드와 마찬가지로 메소드에 사용될 때는 virtual로 선언된 메소드에만 사용이 가능합니다.

C++11에서 final 키워드의 추가로 간단하게 상속을 차단할 수 있는 방법이 생겼고,

override 키워드를 통하여 오버라이딩을 명시하여 사용자의 실수를 줄일 수 있게 되었습니다.

반응형