Private 상속
Student 클래스 예제
인터페이스와 구현
public 상속에서, 클래스는 인터페이스와 구현을 상속한다. (기초 클래스에 있는 순수 가상 함수들은 구현이 없이 인처페이스만 제공할 수 있다.) 인터페이스를 획득하는 것은 is-a 관계의 역할이다. 반면에 컨테인먼트에서는 어떤 클래스가 인터페이스 없이 구현을 획득한다. 인터페이스를 상속하지 않는 것이 has-a 관계의 역할이다.
키워드 explicit
하나의 매개변수로 호출될 수 있는 생성자는, 그 매개변수의 데이터형을 클래스형으로 암시적으로 변환하는 함수로 기능한다는 사실을 기억하라.
컨테인트먼트와 private 상속
컨테인먼트
1. 사용하기 쉽다.
2. 하나 이상의 기초 클래스로부터 클래스를 상속할 때, 상속이 문제를 일으킬 수 있기 때문이다.(다중상속 문제점 예방)
3. 같은 클래스의 종속 객체를 하나 이상 내포시킬 수 있다.
private 상속
protected 멤버에 접근할 수 있다.
가상 함수를 다시 정의할 수 있다.
일반적으로, has-a 관계를 모델링하려면 컨테인먼트를 사용해야 한다. 새 클래스가 오리지널 클래스의 protected 멤버들에 접근할 필요가 있거나, 가상 함수들을 다시 정의할 필요가 있을 경우에는 private 상속을 사용해야 한다.
protected 상속 (TODO 가상 기초 함수 추가)
public, protected, private 상속
특성 | public 상속 | protected 상속 | private 상속 |
public 멤버 | 파생 클래스의 public 멤버 | 파생 클래스의 protected 멤버 | 파생 클래스의 private 멤버 |
protected 멤버 | 파생 클래스의 protected 멤버 | 파생 클래스의 protected 멤버 | 파생 클래스의 private 멤버 |
private 멤버 | 기초 클래스 인터페이스를 통해서만 접근할 수 있다. | 기초 클래스 인터페이스를 통해서만 접근할 수 있다. | 기초 클래스 인터페이스를 통해서만 접근할 수 있다. |
암시적 업캐스팅 | 가능하다 | 파생 클래스 안에서만 가능한다. | 불가능하다. |
using을 사용하여 접근 다시 정의하기
다중 상속
사원 수는 몇 명인가?
클래스가 간접적인 가상 기초 클래스를 가진다면, 가상 기초 클래스의 디폴트 생성자가 필요한 경우를 제외하고, 그 클래스의 생성자는 가상 기초 클래스의 생성자를 명시적으로 호출해야한다.
어느 메서드를 사용하는가?
다중 상속은 모호한 함수 호출을 일으킬 수 있다. 예를 들어, BadDude 클래스는 전혀 다른 두 개의 Draw() 메서드를 Gunslinger 클래스와 PokerPlayer 클래스로부터 각각 상속할 수 있다.
사용 범위 결정 연산자를 사용하면 어느 것을 말하는지 확실하게 할 수 있다.
그러나 더 나은 방법은 SingingWaiter에 대해 Show()를 다시 정의하고, 그것으로 사용할 Show() 버전을 지정하는 것이다.
그러나 다중 상속받는 가지 수의 성분을 사용해야 하기 때문에 이를 극복하고자 점층적 접근 방식 대신 모듈 접근 방식을 사용할 수 있다.
요약하면, 하나의 공통 조상을 공유하는 다중 상속을 사용하려면, 가상 기초 클래스를 도입해야 한다. 그리고 생성자에서 멤버 초기자 리스트의 규칙을 변경하고, 다중 상속을 고려하지 않고 작성한 클래스의 코딩을 변경해야 한다.
가상 기초 클래스와 비교 우위
파생 클래스에 있는 이름은 직접이든 간접이든 간에 조상 클래스에 있는 동일한 이름보다 비교 우위를 가진다.
다중 상속 요약
첫째, 가상 기초 클래스들을 사용하지 않는 다중 상속을 복습해 보자, 이와 같은 형태의 다중 상속은 새로운 규칙을 요구하지 않는다. 그러나 파생 클래스가 서로 다른 기초 클래스로부터 이름이 같은 두 멤버를 상속한다면, 두 멤버를 구분하기 위해 그 파생 클래스에서 클래스 제한자늘 사용할 필요가 있다.
즉, Gunslinger와 PokerPlayer 클래스로부터 파생된 BadDude 클래스의 메서드들은, Gunslinger와 PokerPlayer로부터 각각 상속받은 draw() 메서드들을 구분하기 위해 Gunslineger::draw()와 PokerPlayer::draw()를 사용해야 한다. 그와 같이 사용하지 않으면 모호한 사용이라고 컴파일러가 불평할 것이다.
가상이 아닌 한 기초 클래스로부터 하나 이상의 경로를 통해서 클래스를 상속한다면, 그 파생 클래스는 그 기초 클래스의 가상이 아닌 각 인스턴스마다 하나씩 기초 클래스의 여러 인스턴스는 문제를 일으킬 가능성이 높다.
그 다음에, 가상 기초 클래스들은 사용하는 다중 상속에 대해 살펴보자. 파생 클래스가 파생을 나타낼 때 키워드 virtual을 사용한다면, 그것의 기초 클래스는 가상 기초 클래스가 된다.
class marketing : public virtual reality { ... };
가상 기초 클래스를 사용하는 가장 큰 변화이자 이유는, 하나의 가상 기초 클래스의 여러 인스턴스로부터 상속되는 클래스는, 단 하나의 기초 클래스 객체만 상속한다는 것이다. 이 기능을 구현하려면 다음과 같은 조건도 필요하다.
- 간접적인 가상 기초 클래스를 사용하는 파생 클래스는, 그 파생 클래스의 생성자들이 간접적인 가상 기초 클래스 생성자들을 직접 호출하게 해야 한다. 이것은 가상이 아닌 간접적인 기초 클래스에는 적용되지 않는다.
- 이름의 모호함은 비교 우위 규칙을 통해 해결된다.
다중 상속은 프로그래밍을 조금 복잡하게 만들 수 있다. 그러나 이러한 복잡성의 대부분은, 파생 클래스가 하나의 기초 클래스로부터 하나 이상의 경로를 통해 상속할 때 발생한다. 이러한 상황을 피하기 위해 오직 해야 할 일은, 필요할 경우에 상속받은 이름들을 클래스 이름으로 제한하는 것이다.
클래스 템플릿 (미완)
클래스 템플릿 정의
템플릿 클래스 사용
템플릿 클래스 자세히 들여다보기
배열 템플릿 예제와 데이터형이 아닌 매개변수
템플릿의 융통성
템플릿 특수화
멤버 템플릿
매개변수 템플릿
템플릿 클래스와 프렌드 함수
템플릿 별칭(C++11)
요약
'C++ > C++' 카테고리의 다른 글
16. String 클래스와 표준 템플릿 라이브러리 (미완, 일반화 프로그래밍) (1) | 2023.09.18 |
---|---|
13. 클래스의 상속 (0) | 2023.09.14 |
[C++] Rule of three (0) | 2023.08.27 |
Overloading (0) | 2023.07.28 |
12. 클래스와 동적 메모리 대입, +추가 필요 (0) | 2023.07.25 |