[C++] 상속과 virtual 키워드

junpkim·2022년 7월 25일
0

C++에선 클래스에서 다른 클래스를 상속받아 사용할 수 있고, 상속한 클래스에 이미 정의되어 있는 함수를 재정의하는 오버라이딩이 가능하다.
그리고 상속받은 클래스를 상속한 클래스의 자료형으로 사용하는 업캐스팅이 가능한데, 오버라이딩과 업캐스팅을 둘 다 해주다보면 문제가 발생한다.

class A
{
	public:
		void f() { cout << "A" << endl; }
};

class B : public A
{
	public:
		void f() { cout << "B" << endl; }
};

int main()
{
	A *a = new B();
	B *b = new B();

	a->f();
	b->f();
}

업캐스팅을 하지 않은 b 변수는 f 함수를 실행하였을때 정상적으로 B 클래스의 f 함수가 실행되어 "B" 를 출력하지만, A 클래스로 업캐스팅 된 a 변수는 B 클래스의 생성자를 이용해 생성해주었음에도 A 클래스의 f 함수가 실행되어 "A"를 출력하게 된다.

이 문제를 해결해주기 위한 것이 virtual 키워드이다.
오버라이딩 할 함수의 부모클래스에 있는 함수에 virtual 을 붙여주면

class A
{
	public:
		virtual void f() { cout << "A" << endl; }
};

class B : public A
{
	public:
		void f() { cout << "B" << endl; }
};

업캐스팅한 자식클래스에서도 정상적으로 원래 본인의 함수를 실행해준다.
상속 해줄 클래스를 만들 때 특히 소멸자는 항상 virtual 키워드를 붙여서 선언해주어야 한다.

C++에서는 다중상속을 지원해주는데, 이 경우 다이아몬드 상속에서 문제가 발생한다.

다이아몬드 상속에서는 상속받은 클래스에서 생성자를 호출할 때 상속한 클래스의 생성자를 먼저 호출해주는데, 위 그림에서 B와 C 모두 A를 상속받기 때문에 A 생성자가 두 번 실행되게 된다.

class A
{
	public:
		A() { cout << "A constructor" << endl; }
};

class B : virtual public A
{
	public:
		B() { cout << "B constructor" << endl; }
};

class C : virtual public A
{
	public:
		C() { cout << "C constructor" << endl; }
};

class D : public B, public C
{
	public:
		D() { cout << "D constructor" << endl; }
};

이를 방지하기 위해 다중상속 받을 클래스 B와 C에서 A를 상속 받을 때 앞에 virtual 키워드를 붙여주면 A 생성자가 중복해서 실행되지 않는다.

0개의 댓글