영넌 개발로그

[C++ 기초] Virtual function (destructor, pure) 본문

코딩/C++

[C++ 기초] Virtual function (destructor, pure)

영넌 2020. 12. 6. 06:05

그림과 같은 구조로 클래스 3개가 있다고 생각해보자

class A {
public:
	void iam() {
		cout << "I am A" << endl;
	}
};

class AA : public A {
public:
	void iam() {
		cout << "I am AA" << endl;
	}
};

class AB : public A {
public:
	void iam() {
		cout << "I am AB" << endl;
	}
};

 

 

이때 main문에 아래와 같이 적어준다면, 그림과 같은 상황이 되어서 pa 포인터(부모 포인터)는 부모 클래스만을 가리키고 있게 된다. iam함수를 부르면 A 클래스의 iam함수가 불린다.

A* pa = new AA();

 

 

함수 overloading을 사용해서 불러야하는 번거로움이 있다. 이걸 없앨 수 있을까? virtual function을 사용하자!

void doSomething(A* pa) {
	pa->iam();		//I am A
}

void doSomething(AA* pa) {
	pa->iam();		//I am AA
}

void doSomething(AB* pa) {
	pa->iam();		//I am AB
}



int main() {
	doSomething(new A());
	doSomething(new AA());
	doSomething(new AB());
}

 

 

class 내에 virual을 앞에 붙여 선언을 해주면 virtual function이 된다. 부모 포인터를 사용해서 상속받은 마지막 자식의 함수를 호출할 수 있게 가능하다. 

class A {
public:
	virtual void iam() {
		cout << "I am A" << endl;
	}
};

int main(){
	A* pa = new AA();
	pa->iam();		//I am AA
	pa = new AB();
	pa->iam();		//I am AB
    
    
    return 0;
    
}

 

아까와 같은 함수 오버로딩 상황에서 사용하면 편리하다.

#include <iostream>

using namespace std;

class A {
public:
	virtual void iam() {
		cout << "I am A" << endl;
	}
};

class AA : public A {
public:
	void iam() {
		cout << "I am AA" << endl;
	}
};

class AB : public A {
public:
	void iam() {
		cout << "I am AB" << endl;
	}
};

void doSomething(A* pa) {
	pa->iam();		
}

int main() {
	
	doSomething(new A());	//I am A
	doSomething(new AA());  //I am AA
	doSomething(new AB());  //I am AB
}

 

 

 

Virtual function by Reference

virtual function은 상속받은 마지막 자식의 함수를 호출하므로 AA가 나온다.

int main() {
	AA aa;
	A& ra = aa;		//ra라는 이름만 붙인것

	ra.iam();		//I am AA

 

 

Virtual destructor

자식을 지운 후에 부모를 지워야 하므로 virtual로 만들어진 함수를 쓸 경우에는 destructor 앞에도 virtual을 붙여주어야 한다. 

 

pure virtual function

아래 코드에서 foo와 같은 함수를 의미한다. 실체가 없는 함수이다. 자기로 부터 상속 받은 자식들은 무조건 이 함수를 가지고 있어야 한다. pure virtual 함수를 가지고 있는 class로부터는 절대로 객체를 만들 수 없기 때문이다.  개발자들에게 오류가 발생하는 것을 막을 수 있다.

class A {
public:
	virtual ~A() {
		cout << "Destructor A" << endl;
	}
	virtual void iam() {
		cout << "I am A" << endl;
	}
	virtual void foo() = 0; // pure virtual function
};

Comments