private 상속의 의미는 is-implemented-in-terms-of이다. 파생 클래스 쪽에서 기본 클래스의 protected 멤버에 접근해야 할 경우 혹은 상속받은 가상 함수를 재정의해야 할 경우에 private 상속이 의미가 있다. 객체 합성과 달리, private 상속은 공백 기본 클래스 최적화(EBO)를 활성화시킬 수 있다. private 상속 public 상속은 is-a 관계로 나타낸다. 하지만, private 상속은 is-a 관계로 나타내지 않는다. class Person { ... }; class Student: private Person { ... }; void eat(const Person& p); void study(const Student& s); Person p; Studne..
객체 합성의 의미는 public 상속이 가진 의미와 완전히 다르다. 응용 영역에서 객체 합성의 의미는 has-a이다. 구현 영역에서는 is-implemented-in-terms-of의 의미이다. has-a, is-implemented-in-terms-of 객체 합성 어떤 타입의 객체들이 그와 다른 타입의 객체들을 포함하는 경우를 합성이라고 한다. class Address { ... }; class phoneNumber { ... }; class Person { public: ... private: std::string name; Address address; PhoneNumber voiceNumber; PhoneNumber faxNumber; }; Person객체는 string, Address, Phon..
상속받은 기본 매개변수 값은 절대로 재정의해서는 안된다. 기본 매개변수 값은 정적으로 바인딩되는 반면, 가상 함수는 동적으로 바인딩되기 때문이다. 상속받은 기본 매개변수 값 재정의 금지 C++에서 상속받을 수 있는 함수의 종류는 가상 함수와 비가상 함수로 두 가지이다. 가상 함수는 동적으로 바인딩되고 비가상 함수는 정적으로 바인딩된다. (정적 바인딩은 선행 바인딩, 동적 바인딩은 지연 바인딩이라고도 불린다.) 또한, 기본 매개변수 값도 정적으로 바인딩된다. class Shpae { public: enum ShapeColor { Red, Green, Blue }; virtual void draw(ShpaeColor color = Red) const = 0; ... }; class Rectangle: pub..
상속받은 비가상 함수를 재정의하는 일은 절대로 하지 마라. 상속받은 비가상 함수 재정의 금지 상속받은 비가상 함수를 재정의하는 일은 절대로 해서는 안된다. class B { public: void mf(); ... }; class D: public B { ... }; D 클래스가 B 클래스로부터 public 상속되어 파생되었고, B 클래스에는 mf라는 이름의 public 멤버 함수가 정의되어 있다고 가정해 보자. D x; // D타입 객체 B *pB = &x; pB->mf(); // B::mf 문제없이 동작할 것이다. 하지만, mf함수를 상속한다면 문제가 발생한다. class D: public B { public: void mf(); ... }; D x; B *pB = &x; pB->mf(); // B:..
가상 함수 대신에 쓸 수 있는 다른 방법으로 NVI 관용구 및 전략 패턴이 있다. 이 중 NVI 관용구는 그 자체가 템플릿 메서드 패턴의 한 예이다. 객체에 필요한 기능을 멤버 함수로부터 클래스 외부의 비멤버 함수로 옮기면, 그 비멤버 함수는 그 클래스의 public 멤버가 아닌 것들을 접근할 수 없다는 단점이 생긴다. tr1::function 객체는 일반화된 함수 포인터처럼 동작한다. 이 객체는 주어진 대상 시그니처와 호환되는 모든 함수 호출성 개체를 지원한다. 가상 함수 대체 방법 가상 함수 대신 사용할 방법들이 몇 가지 있다. 게임 캐릭터 클래스를 설계하는 상황을 가정해 보자. class GameCharacter { public: virtual int healthValue() const; ... }..
인터페이스 상속은 구현 상속과 다르다. public 상속에서, 파생 클래스는 항상 기본 클래스의 인터페이스를 모두 물려받는다. 순수 가상 함수는 인터페이스 상속만을 허용한다. 단순 가상 함수는 인터페이스 상속과 더불어 기본 구현의 상속도 가능하도록 지정한다. 비가상 함수는 인터페이스 상속과 더불어 필수 구현의 상속도 가하도록 지정한다. 인터페이스 상속과 구현 상속의 차이 상속은 크게 두 가지로 나눌 수 있다. 하나는 함수 인터페이스의 상속이고, 또 하나는 함수 구현의 상속이다. 클래스 설계자의 입장에서 보면, 멤버 함수의 인터페이스만을 파생 클래스에 상속받고 싶을 때가 있다. 어쩔 때는 함수의 인터페이스 및 구현을 모두 상속받고 그 상속받은 구현이 오버라이드가 가능하게 만들고 싶을 때도 있다. 반대로, ..
파생 클래스의 이름은 기본 클래스의 이름을 가린다. public 상속에서는 이런 이름 가림 현상은 바람직하지 않다. 가려진 이름을 다시 볼 수 있게 하는 방법으로, using 선언 혹은 전달 함수를 쓸 수 있다. 상속된 이름이 숨겨지는 것을 피해라 상속과 관련된 이름 가리기 현상을 보기 전, 이해를 돕기 위해 기본 변수에 대한 이름 가리기 규칙을 살펴보자. int x; void someFunc() { double x; std::cin >> x; } 값을 읽어 x에 넣는 위의 문장에서 실제로 참조하는 x는 전역 변수 x가 아니라 지역 변수 x이다. 이유는 안쪽 유효범위에 있는 이름이 바깥쪽 유효범위에 있는 이름을 가리기 때문이다. 컴파일러가 someFunc의 유효범위 안에서 x라는 이름을 만나면, 일단 그..