LANG/C++

[C++]08-2.가상함수(Virtual Function)

혀니리리 2023. 5. 16. 12:16
728x90
class Base
{
public:
	void BaseFunc(){cout << "Base Function" << endl;}
};

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

일때, 

 

int main(void)
{
	Base *bptr = new Derived(); //컴파일 OK!
	bptr->DerivedFunc();		//컴파일 Error!
    Derived *dptr = bptr;		//컴파일 Error!
}

C++컴파일러는 포인터 연산의 가능성 여부를 판단할 때 포인터의 자료형을 기준으로 판단하기 때문.

 

하지만 이건 됨

int main(void)
{
	Derived *dptr = new Derived();	//컴파일 OK!
    Base *bptr = dptr				//컴파일 OK!
}

dptr은 Derived클래스의 포인터 변수니까, 이 포인터가 가리키는 객체는 분명 Base클래스를 직 or 간접적으로 상속하는 객체임. 그러니 Base형 포인터 변수로도 참조가 가능!!

 

해석)

1)fptr이 First형 포인터니, 이 포인터가 가리키는 객체를 대상으로 First클래스에 정의된 MyFunc함수는 무조건 호출할 수 있겠구나

2)sptr이 Second형 포인터니, 이 포인터가 가리키는 객체에는 First의 MyFUnc함수와 Second의 MyFunc함수가 오버라이딩 관계로 존재하는군! 그럼 오버라이딩한 Second의 MyFunc함수를 호출해야겠다!

 

알 수 있는 것: 그냥 무작정 각자 객체의 함수를 바로 참조한 것처럼 보이지만 사실 오버라이딩 따진 것

 

이렇게 자료형만으로 호출되는 함수가 바뀌면 문제가 됨. 이를 해결하기 위한 것이 가상함수

 

가상함수

앞에 virtual을 붙인다.

결과

ThirdFunc

ThirdFunc

ThirdFunc

이렇게 하면 해당 함수 호출 시, 포인터의 자료형을 기반으로 호출대상 결정하지 X,포인터 변수가 실제로 가리키는 객체를 참조하여 호출의 대상을 결정.

 

순수 가상함수

class Employee처럼 기초 클래스의 의미만 가질 뿐, 실제로 객체생성을 목적으로 존재하지 않는 함수도 있는데

프로그래머들은 이런걸로 객체를 생성하는 실수를 저지를 수 있음. 이럴 때를 위한 함수

몸체가 정의되지 않은 함수

이점: 1)잘못된 객체의 생성을 막을 수 있음

         2)보다 정확한 명시 가능

하나 이상의 멤버함수를 순수 가상함수로 선언한 클래스를 '추상 클래스(absract class)'라고 부름.

 

다형성 : 가상함수의 호출관계에서 보인 특성

모습은 같은데 형태는 다르다(=문장은 같은데 결과는 다르다)

class First
{
public:
	virtual void SimpleFunc(){cout <<"First" <<endl;}
};
class Second:public First
{
public:
	virtual void SimpleFunc(){cout <<"Second" << endl;}
}

=> 다형성.

728x90