반응형
(42Seoul의 CPP03 과제를 진행하며 공부한 내용을 작성한 TIL을 정리한 글 입니다.)
개념 공부📓
클래스 상속
- 기존 클래스의 특성과 기능을 새로운 클래스가 물려받는 것
- 상속을 통해 기존 클래스의 멤버 변수와 멤버 함수를 그대로 사용하거나, 새로운 멤버 변수와 멤버 함수를 추가하여 새롭게 정의할 수 있음
- 상속을 통해 만들어진 새로운 클래스를 ‘파생 클래스’ 또는 ‘하위 클래스’ 라고 하며, 기존 클래스는 ‘기본 클래스’ 또는 ‘상위 클래스’ 라고 함
- 클래스 상속 방법
class BaseClass {
// 기본 클래스의 멤버 변수와 멤버 함수 선언
}
class DerivedClass : access-specifier BaseClass {
// 파생 클래스의 멤버 변수와 멤버 함수 선언
}
- BaseClass : 기본 클래스
- DerivedClass : 파생 클래스로, ‘BaseClass’를 상속하는 것을 나타내기 위해 콜론(’:’) 뒤에 ‘access-specifier BaseClass’ 와 ‘BaseClass’ 를 명시함
- ‘access-specifier BaseClass’ : 접근 제어 지시자로, 기본 클래스의 멤버들에 대한 파생 클래스의 접근 권한을 설정. 주로 ‘public’, ‘protected’, ‘private’ 키워드를 사용함
- public : 기본 클래스의 public, protected, private 멤버들이 그대로 상속됨
- protected : 기본 클래스의 protected 지시자보다 접근 범위가 넓은 멤버(public)는 protected 로 변경되어 상속됨
- private : 기본 클래스의 private 지시자보다 접근 범위가 넓은 멤버(public, protected)는 private 으로 변경되어 상속됨
클래스 상속 함수 오버라이딩
class Base {
public:
virtual void printMessage() const {
std::cout << "This is Base class" << std::endl;
}
};
class Derived : public Base {
public:
// Base 클래스의 printMessage() 함수를 오버라이딩
void printMessage() const override {
std::cout << "This is Derived class" << std::endl;
}
};
int main() {
Base baseObj;
Derived derivedObj;
// 기존 클래스의 함수 호출
baseObj.printMessage(); // 출력: "This is Base class"
// 파생 클래스에서 오버라이딩한 함수 호출
derivedObj.printMessage(); // 출력: "This is Derived class"
return 0;
}
- 기존 클래스에서 상속받은 함수를 파생 클래스에서 수정하여 사용하고 싶을 경우, 함수 오버라이딩을 통해 해당 함수를 새로 정의하면 됨
- 함수 오버라이딩을 위해 다음의 조건을 만족해야 함
- 기존 클래스에서 오버라이딩 하려는 함수는 가상(virtual) 함수로 선언되어야 함
- 기존 클래스의 함수와 함수의 이름, 반환 타입, 매개변수 리스트가 동일해야 함
클래스 상속 생성자 오버라이딩
class Base {
public:
int value;
Base() : value(0) {
std::cout << "Base default constructor called." << std::endl;
}
Base(int val) : value(val) {
std::cout << "Base parameterized constructor called." << std::endl;
}
};
class Derived : public Base {
public:
// 기본 클래스의 생성자를 오버라이딩
Derived() : Base() {
std::cout << "Derived default constructor called." << std::endl;
}
// 기본 클래스의 생성자를 오버라이딩하며 추가적인 파라미터 사용
Derived(int val) : Base(val) {
std::cout << "Derived parameterized constructor called." << std::endl;
}
};
int main() {
Base baseObj; // 출력: "Base default constructor called."
Derived derivedObj; // 출력: "Base default constructor called.", "Derived default constructor called."
Base baseObj2(42); // 출력: "Base parameterized constructor called."
Derived derivedObj2(99); // 출력: "Base parameterized constructor called.", "Derived parameterized constructor called."
return 0;
}
- 생성자와 소멸자 오버라이딩은 위의 함수 오버라이딩과 다름
- 상속된 변수들의 초기화는 기존 클래스의 생성자에서 진행하기 때문에, 파생 클래스의 생성자에서 기본 클래스의 생성자를 호출해야 함.
- 오버라이딩 시, 파생 클래스의 생성자가 호출되면 먼저 기본 클래스의 생성자가 호출되고, 이후 파생 클래스의 생성자가 실행됨.
다이아몬드 상속
- 하나의 클래스가 두개 이상의 클래스로부터 상속 받는 구조
A
/ \
B C
\ /
D
- 다이아몬드 상속에는 D 클래스에서 A 클래스의 멤버 변수나 멤버 함수에 접근할 때, B나 C 중 어떤 클래스를 기반으로 하는지 모호하다는 문제가 있어 잘 사용하지 않는 상속 방법
- C++ 에는 다이아몬드 문제를 해결하기 위해 가상 상속을 지원함.
- 가상상속은 다이아몬드 상속 구조에서 공통된 기본 클래스를 가상으로 상속하여, 다이아몬드 구조를 일반적인 트리구조로 바꿔주는 기법
- virtual 키워드를 사용하여 공통된 클래스를 가상으로 상속
class A {
// ...
};
class B : virtual public A {
// ...
};
class C : virtual public A {
// ...
};
class D : public B, public C {
// ...
};
- B 와 C에서 A의 멤버변수와 멤버함수를 공유하기 때문에, B > C 순서로 생성자가 호출되며 A의 멤버변수를 초기화할 경우, C의 내용으로 덮어쓰기 됨
제가 공부한 내용을 기록하고 있습니다.
혹시 수정이 필요한 부분이 있다면, 댓글로 지적 부탁드립니다!
선한 관심과 도움 감사드립니다😊
반응형
'C++' 카테고리의 다른 글
[C++] 42SEOUL CPP04 개념 공부하기 (0) | 2023.07.28 |
---|---|
[C++] 42SEOUL CPP02 개념 공부하기 (0) | 2023.07.28 |
[C++] 42SEOUL CPP01 개념, 함수 공부하기 (0) | 2023.07.28 |