<객체> 9. 가상 함수와 추상 클래스

정지민·2023년 11월 9일
0

객체 프로그래밍

목록 보기
8/11

가상함수

  • virtual 키워드로 선언
  • 동적 바인딩 지시어

함수 오버라이딩

  • 파생 클래스에서 기본 클래스의 가상 함수와 동일한 이름의 함수 선언
  • 기본 클래스의 가상 함수의 존재감 상실
  • 조건 : 가상 함수 이름, 매개 변수 타입과 개수, 리턴 타입이 모두 일치해야 함

오버라이딩 시 virtual 지시어 생략 가능
private, protected, public 중 자유롭게 지정 가능

-> 가상 함수를 재정의하는 것을 오버라이딩, 그렇지 않는 경우를 함수 재정의로 구분

동적 바인딩

  • 기본 클래스에 대한 포인터로 가상 함수를 호출하는 경우
  • 객체 내에 오버라이딩한 파생 클래스의 함수를 찾아 실행

범위 지정 연산자(::)

기본클래스::가상함수() 형태로 기본 클래스의 가상 함수를 정적 바인딩으로 호출

class Shape {
public:
	virtual void draw() { 
		...
	}
};

class Circle : public Shape {
public:
	virtual void draw() { 
		Shape::draw(); // 기본 클래스의 draw()를 실행한다.
			.... // 기능을 추가한다.
	}
};

가상 소멸자

  • 소멸자를 virtual 키워드로 선언
  • 파생 클래스의 소멸자가 자신의 코드 실행 후, 기본 클래스의 소멸자를 호출하도록 컴파일됨

기본 클래스의 포인터 활용

  • 기본 클래스의 포인터로 파생 클래스 접근
  • pStart, pLast, p의 타입이 Shape*
  • 링크드 리스트를 따라 Shape을 상속받은 파생 객체들 접근
  • p->paint()의 간단한 호출로 파생 객체에 오버라이딩된 draw() 함수 호출

순수 가상 함수

  • 파생 클래스에서 재정의할 함수를 알려주는 역할
  • 실행할 코드를 작성할 목적이 아님
  • 함수의 코드가 없고 선언만 있는 가상 멤버 함수
    멤버 함수의 원형=0;
class Shape {
public:
	virtual void draw()=0; // 순수 가상 함수 선언
};

추상 클래스

최소한 하나의 순수 가상 함수를 가진 클래스

class Shape { // Shape은 추상 클래스
	Shape *next;
public:
	void paint() {
		draw();
	}
	virtual void draw() = 0; // 순수 가상 함수
};
void Shape::paint() {
	draw(); // 순수 가상 함수라도 호출은 할 수 있다.
}

특징

  1. 온전한 클래스가 아니므로 객체 생성 불가능
Shape shape; // 컴파일 오류
Shape *p = new Shape(); // 컴파일 오류
  1. 추상 클래스의 포인터는 선언 가능
    Shape *p;

목적 : 상속에서 기본 클래스의 역할을 하기 위함

  • 추상 클래스를 단순 상속하면 자동 추상 클래스
  • 추상 클래스를 상속받아 순수 가상 함수를 오버라이딩
    -> 파생 클래스는 추상 클래스가 아님
class Shape {
public:
	virtual void draw() = 0;
};

class Circle : public Shape {
public:
	virtual void draw() {
		cout << "Circle";
	}
	string toString() { return "Circle 객체"; }
};


Shape shape; // 객체 생성 오류
Circle waffle; // 정상적인 객체 생성

0개의 댓글