인기 글
-
6. 상속, 그리고 객체 지향 설계
항목 39: private 상속은 심사숙고해서 구사하자
C++은 public 상속을 is-a 관계로 나타낸다.(항목 32 참고) Student가 Person으로부터 public 상속으로 파생된 형태의 클래스 계통이 주어졌다고 가정하면, 함수 호출을 성공시키기 위해 컴파일러가 Student를 Person으로 암시적 변환을 수행하는 예제를 통해 is-a 관계를 설명했었다. 이 예제를 private 상속으로 살짝 바꿔보자. private 상속은 분명 is-a 관계를 뜻하지 않는다. 그럼 뭘까? 일단 private 상속의 동작 규칙부터 알아보자. private 상속의 동작 규칙 파생 클래스 객체(Student)를 기본 클래스(Person)으로 변환하지 않는다. 기본 클래스로부터 물려받은 맴버는 파생 클래스에서 모조리 private 맴버가 된다. 즉 기본 클래스에서 ..
-
6. 상속, 그리고 객체 지향 설계
항목 36: 상속받은 비가상 함수를 파생 클래스에 재정의하는 것은 절대 금물!
D라는 이름의 클래스가 B라는 이름의 클래스로부터 public 상속에 의해 파생되었고, B 클래스에는 mf()라는 public 맴버 함수가 정의되어 있다고 가정해보자. 여기서의 pB->mf() 이 당연히 이런식으로 동작할 것이라고 예상할 수 있다. 왜? 둘 다 같은 객체인 x에 대해 mf()를 호출하고 있기 때문이다. 하지만 당연하지 않을 수도 있다는 것이 문제이다. 특히 mf()가 비가상 함수이고 D 클래스가 자체적으로 mf() 함수를 또 정의하고 있는 경우 아래 코드와 같은 황당한 일이 벌어진다. 이렇게 같은 객체에서 같은 함수를 호출하는데, 실제로는 다른 함수를 호출하는 이유는, 비가상 함수는 정적 바인딩(static binding)으로 묶이기 때문이다.(항목 37 참고) => 즉 pB가 가르키는 ..
-
6. 상속, 그리고 객체 지향 설계
항목 34: 인터페이스 상속과 구현 상속의 차이를 제대로 파악하고 구별하자
(public)상속 이라는 개념은 사실 2가지로 나뉜다. 인터페이스 상속 vs (함수)구현 상속 이 둘의 차이는 함수 선언과 함수 정의의 차이와 맥을 같이한다고 보면 된다. 클래스 설계자의 입장에서 맴버 함수의 인터페이스(선언)만을 파생클래스에 상속받고 싶은 경우 함수의 인터페이스 구현을 모두 상속받고 싶은 경우 상속받은 구현이 오버라이드가 가능하게 만들고 싶은 경우 어떤 것도 오버라이드할 수 없도록 막고 싶은 경우 이러저러한 선택사항이 나올 수 있는데, 이러한 선택사항들 사이의 차이점을 명확하게 몸으로 느끼는 것이 중요하다. 그래서 예를 들어보면, 그래픽 응용프로그램에 쓰이는 기하학적 도형을 나타내는 클래스 계통구조를 놓고 한번 생각해보자. Shape는 추상 클래스이다. 왜냐하면 맴버 함수인 draw(..
-
2. 생성자, 소멸자 및 대입 연산자
항목 6: 컴파일러가 만들어낸 함수가 필요없으면 확실히 이들의 사용을 금해 버리자.
부동산 거래 프로그램을 만든다. 그래서 class HomeforSale을 만드는데, 부동산 중개 업자가 꼭 신신당부한 말이 있다. 모든 자산은 세상에 하나밖에 없다!! 그럼 HomeForSale은 사본자체를 만들 수 없게 해야 한다. 그러다 보니 HomeForSale 객체를 복사하려 하면 컴파일 에러가 뜨게 하고 싶다. 일반적으로 어떤 클래스에서 특정한 종류의 기능을 지원하지 않았으면 하는 의도를 반영할려면, 그런 기능을 제공하는 함수를 선언하지 않으면 되는데, 복사 생성자와 복사 대입 연산자의 경우는 선언하지 않으면 컴파일러가 자동으로 선언해버리는게 문제다. 해결의 열쇠 : 기본 복사 생성자, 기본 복사 대입 연산자는 public member로 선언된다!! => private으로 바꿔버리면 됨 => 외..
-
1. C++에 왔으면 C++ 법을 따릅시다
항목 4: 객체를 사용하기 전에 반드시 그 객체를 초기화 하자
객체의 초기화에 있어서는 C++이 이랬다저랬다 하는 경향이 있다.(맘에 들지 않음) int x; 이 코드가 어떤 상황에서는 0으로 자동 초기화가 되지만, 또 다른 상황에서는 그렇지 않다는 것이다. class Point{ int x, y; }; Point p; 이렇게 했을 때에도, p의 데이터 맴버(x,y) 역시 어떤 상황에서는 0으로 자동 초기화가 되지만, 또 다른 상황에서는 안된다. => ???????????? 초기화되지 않은 값을 만약 그대로 읽으면 C++에서는 그대로 흘러 나오게 된다. 다른 언어에서는 뭐 초기화되지 않은 객체를 읽기만 해도 프로그램이 멈추는 경우도 있지만… C++의 객체 초기화가 중구난방인건 절대 아니다. 언제 초기화가 보장되며, 언제 그렇지 않은지에 대한 규칙이 명확하게 있지만,..