C++ - virtual) 복습을 위해 작성하는 글 2023-11-06

rizz·2023년 11월 6일
0

C

목록 보기
20/25

📒 C++ - virtual

📌 virtual이란?

- virtual 키워드를 붙임으로써, 파생 클래스에서 재정의할 것으로 기대하는 함수 또는 소멸자에 붙인다.

- virtaul 키워드를 사용하여 가상 함수를 선언하였다면, 파생 클래스에서 재정의한 멤버 함수 또한 자동으로 가상 함수로 선언이 된다. 이때, 파생 클래스의 멤버 함수에는 virtual 키워드를 붙이지 않아도 가상 함수로 선언이 되지만, 가독성을 위해 붙이는 것이 좋다.

- 파생 클래스에서 재정의할 가능성이 있는 함수는 모두 가상 함수로 선언하는 것이 좋다.

// C++
#include <iostream>

using namespace std;

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

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

class Derived1 : public Derived
{
	void func()
	{
		cout << "Derived1" << endl;
	}
};

void foo(Base& base)
{
	base.func();
}

int main()
{
	Base b;
	Derived d;

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

	Base& b0 = d;
	b0.func();

	Base* b1 = &d;
	b1->func();

	foo(b);
}

Output:
Base
Derived
Base
Base
Base

- Base 클래스의 func 함수에 virtual 키워드를 붙이지 않았을 때는 자료형의 클래스로 함수를 호출한다.

 

// C++
#include <iostream>

using namespace std;

class Base
{
public:
	virtual void func()
	{
		cout << "Base" << endl;
	}
};

class Derived : public Base
{
public:
	void func() // 자식 클래스에 오버라이딩 된 함수에도 virtual이 적용된다.
	{
		cout << "Derived" << endl;
	}
};

class Derived1 : public Derived
{
	void func()
	{
		cout << "Derived1" << endl;
	}
};

void foo(Base& base)
{
	base.func();
}

int main()
{
	Base b;
	Derived d;

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

	Base& b0 = d;
	b0.func();

	Base* b1 = &d;
	b1->func();

	foo(b);
}

Output:
Base
Derived
Derived
Derived
Base

- Base 클래스의 func 함수에 virtual 키워드를 붙였을 경우에는 해당 객체의 클래스로 위임하여 함수를 호출한다.

- 위 예제의 파생 클래스들의 멤버 함수에는 virtual 키워드를 붙이지 않아도 가상 함수 처리가 되지만, 명시적으로 virtual 키워드를 붙여주는 것이 좋다.

 

📌 가상 소멸자

// C++
#include <iostream>

using namespace std;

class Character
{
public:
	 ~Character()
	{
		cout << "~Character" << endl;
	}

};

class Player : public Character
{
public:
	~Player()
	{
		cout << "~Player" << endl;
	}
};

int main()
{
	Character* ch = new Player;
	delete ch;
}

Output:
~Character

- Character 클래스와 Player 클래스 모두 소멸자가 호출돼야 했지만, Character 클래스의 소멸자만 호출되어 메모리 누수가 발생하였다.

- 이를 해결하기 위해서는 부모 Character 클래스의 소멸자에 virtual 키워드를 붙여줌으로써 해결할 수 있다.

 

// C++
#include <iostream>

using namespace std;

class Character
{
public:
	virtual ~Character()
	{
		cout << "~Character" << endl;
	}

};

class Player : public Character
{
public:
	 ~Player()
	{
		cout << "~Player" << endl;
	}
};

int main()
{
	Character* ch = new Player;
	delete ch;
}

Output:
~Player
~Character

- 부모 클래스의 소멸자만 virtual 키워드를 붙여주면 파생 클래스의 소멸자들도 모두 가상 소멸자로 선언이 된다.

- 예제와 같이 virtual 소멸자로 선언하게 되면 가장 아래 계층의 소멸자가 가장 먼저 호출이 되고, 부모의 소멸자가 호출되게 된다.

profile
복습하기 위해 쓰는 글

0개의 댓글