Cpp - 오버로딩, 오버라이딩, 가상 함수

eelijus·2022년 5월 6일
0

Cpp/C++

목록 보기
3/10

💡 오버로딩, 오버라이딩, 가상 함수

오버로딩(overloading)과 오버라이딩(overriding), 가상 함수

오버라이딩 : 주로 상속에서 쓰이며, 동일한 함수명에 대해 원래 기능을 무시하고 새롭게 재정의하는 것.

오버로딩 : 동일한 함수명을 가진 함수를 매개변수를 달리 해 여러개로 정의하는 것.

오버로딩과 오버라이딩은 헷갈리기 쉽다. 표로 정리해보자

오버로딩(overloading)오버라이딩(overriding)
매개변수변경변경 X 함수 원형 유지동
동작 기능기능 유지기능 변경 또는 확장

오버로딩 시 함수의 기능을 변경해도 되지만, 주로 동일한 기능을 다양한 인자를 받아들여 쓰기 위해 사용하는 경우가 대부분.


멤버 함수 오버라이딩

상속을 통해 물려받은 멤버 함수를 오버라이딩을 통해 재정의할 것이다.

  1. 자식 클래스에서 직접 오버라이딩
  2. virtual 함수(가상 함수)를 이용하여 오버라이딩

1. 자식 클래스에서 직접 오버라이딩

#include <iostream>

class Person {
	private:
			std::string name;
	public:
			Person(std::string n) : name(n) {};
			void printInfo() {
				std::cout << "name : " << name << std::endl;
			}
};

class Student: public Person {
	private:
			int stu_num; 
	public:
		Student(std::string n, int sn) : Person(n), stu_num(sn) {};
		void printInfo() {
			Person::printInfo();
			std::cout << "studnet number : " << stu_num << std::endl;
		}
};

int main() {
	Student sujilee("sujilee", 14);

	sujilee.printInfo();
	std::cout << std::endl;
	sujilee.Person::printInfo();
}

Person에 정의된 함수 printInfo()와 동일한 원형을 지니고, 기능부분을 학번까지 출력하도록 재정의 했음.

//OUTPUT

name : sujilee
studnet number : 14

name : sujilee

2. virtual 함수를 이용한 오버라이딩

  • virtual 함수를 이요한 오버라이딩은 언제 필요할까?

위의 코드에서 main문을 조금 바꿔보자.

int main() {
	Person *pointedPerson;
	Person kchoi("kchoi");
	Student sujilee("sujilee", 14);

	pointedPerson = &kchoi;
	pointedPerson->printInfo();

  std::cout << std::endl;
  
	pointedPerson = &sujilee;
	pointedPerson->printInfo();
}

클래스 포인터 변수를 생성했다. 포인터 변수에 Student 클래스의 객체를 참조하게 하면 Student 클래스의 오버라이딩 된 printInfo()가 아니라 Person 클래스의 printInfo()가 호출되는 것을 출력결과에서 확인할 수 있다.

name : kchoi
  
name : sujilee

클래스 포인터 변수는 해당 변수의 타입에 해당하는 클래스의 멤버만 호출할 수 있다.


위와 같은 경우를 해결하는 방법이 바로 virtual 함수 (가상 함수)를 이용한 오버라이딩이다.

#include <iostream>

class Person {
	private:
			std::string name;
	public:
			Person(std::string n) : name(n) {};
			virtual void printInfo() {
				std::cout << "name : " << name << std::endl;
			}
};

class Student: public Person {
	private:
			int stu_num; 
	public:
		Student(std::string n, int sn) : Person(n), stu_num(sn) {};
		virtual void printInfo() {
			Person::printInfo();
			std::cout << "studnet number : " << stu_num << std::endl;
		}
};

int main() {
	Person *pointedPerson;
	Person kchoi("kchoi");
	Student sujilee("sujilee", 14);

	pointedPerson = &kchoi;
	pointedPerson->printInfo();
  
  std::cout << std::endl;

	pointedPerson = &sujilee;
	pointedPerson->printInfo();
}

함수 타입에 virtual 키워드를 붙여주었다.

name : kchoi

name : sujilee
studnet number : 14

virtaul을 이용하여 함수를 가상 함수로 선언하면, 포인터 변수의 타입(25번째줄의 Person)이 아닌 포인터가 실제로 담고있는 객체(34번째줄의 sujilee)의 주소에 따라 호출하는 대상을 바꿀 수 있다.

가상함수에 관련해 알아야할 동적 바인딩(dynamic binding)과 가상 소멸자(virtual destrucor)에 대해서는 다음 게시물에서 다루도록 하겠다.

profile
sujileelea

0개의 댓글