추상 클래스
- 추상 메소드를 한 개 이상 가지고 있는 클래스
- 추상 클래스로는 인스턴스를 생성할 수 없다.
- 추상 클래스를 상속 받은 자식 클래스는 추상 메소드를 모두 구현해야 한다.
- 만약 구현하지 않으면, 자식 클래스도 추상 클래스가 된다.
추상 메소드 (순수 가상 함수)
class Person { //추상 클래스
public:
virtual void sleep() = 0; //순수 가상 함수
};
class Student : public Person {
public:
void sleep() {
cout << “10시 취침" << endl;
}
};
다형성
- 같은 대상이라도 문맥이나 상황에 따라 다르게 사용될 수 있다는 원리
- ex) 스케치북에 도형을 그렸다 - 도형은 삼각형, 사각형, 원이 될 수 있음
- 상위(부모) 클래스로 하위(자식) 클래스의 인스턴스를 생성할 수 있다
캐스팅
업캐스팅
- 자식 클래스의 객체가 부모 클래스 타입으로 형변환 되는 것
- 부모 클래스의 포인터로 자식 클래스 객체를 가리키는 것
다운캐스팅
소멸자
가상함수
- 부모 클래스에서 상속받을 클래스에서 재정의할 것으로 기대하고 정의해 놓은 함수
- 실행 중(런타임)에 어떤 함수를 호출할 것인지 결정함 => 동적 바인딩 (지연 바인딩)
- 포인터나 참조를 통해 호출될 때만 동적 바인딩을 함
생성자, 소멸자, 가상함수, 업캐스팅 예제
- Person p;
- 정적 메모리
- 스택영역에 저장됨. 해제를 명시적으로 할 필요 X, 자동 해제
- Person* p2 = new Person();
- 동적 메모리
- 힙영역에 저장됨. 해제를 명시적으로 해야함
- 필요없을 때 delete
- 업캐스팅한 메모리를 해제하기
- 부모 클래스의 소멸자를 가상함수로 만들어야함
- Person소멸자 호출-> 가상함수네 -> 자식의 소멸자 기대-> 자식의 소멸자 실행->부모 소멸자 실행
class Person {
public:
Person() {} // Person 생성자
virtual void sleep() { //가상 함수 : 동적 바인딩을 하기 위해
cout << "잠자기" << endl;
}
virtual ~Person() {} // Person 소멸자(가상함수)
};
class Student : public Person {
public:
Student() : Person() {} // Student 생성자
void sleep() { // 가상 함수를 재정의(오버라이딩)한 것
cout << "10시에 잠자기" << endl;
}
~Student() {} // Student 소멸자
cout << "Student 소멸자 입니다" << endl;
}
};
int main() {
Student s = Student();
//Person 생성자 실행
//Student 생성자 실행
Student* s2 = new Student();
//Person 생성자 실행
//Student 생성자 실행
delete s2;
//Student 소멸자 실행
//Person 소멸자 실행
s.sleep(); // 정적 바인딩
Person* s3 = new Student(); //업캐스팅
s3->sleep(); // 동적 바인딩
Person p = Student(); //업캐스팅이 아님
p.sleep(); // 동적 바인딩이 일어나지 않음
delete s3; //Person만 소멸, Student 남아있음
// 업캐스팅시 제대로 메모리를 해제하려면 부모 클래스의 소멸자를 가상함수로 만들어야함
//Person소멸자 호출-> 가상함수네 -> 자식의 소멸자 기대-> 자식의 소멸자 실행->부모 소멸자 실행
return 0;
}
static(정적) 멤버
- 클래스에는 속하지만, 객체 별로 할당되지 않고 클래스의 모든 객체가 공유하는 멤버
- 객체와 독립적이므로 객체를 생성하지 않아도 접근 가능
- static 메소드 안에서는 일반 멤버에 접근할 수 없다. (static 멤버에만 접근 가능)
파일 분할
- 기능이 많아지고 코드가 길어지면 프로젝트 관리가 힘들어지므로 파일을 분할하여 관리
- 헤더 파일(.h) : 클래스, 함수 등의 선언부 코드
- 소스 파일(.cpp) : 클래스, 함수 등의 구현부 코드
파일 분할 시 문제점
- 무한 참조 현상이 발생할 수 있다.
- #pragma once : 한번 읽으면 추가적으로 읽지 않도록 하는 기능, 빌드 시간을 줄일 수 있다.
#ifndef __TEST_H__ //__TEST_H__가 정의되지 않았다면
#define __TEST_H__ //정의한다
#endif