Imported from TiStory (2009.05.03) -------------------------------------------------------------------------------------------------- 이번 챕터에서는 C++ 클래스에 대해 컴파일러가 암묵적으로 생성하는 함수들에 대해 이야기하면서,이러한 바탕 하에서 파생 클레스들에 대해 어떠한 규칙들을 강제할 수 있는지 설명하고 있다. 역시나 기본적인 내용이지만, 중요한 기본이기에 짚고 넘어가도록 하자. 신참 질문 하나의 클래스에 대해 암묵적으로 선언, 정의되는 함수들은 무엇이며, 선언과 정의되는 때는 언제인가? C++ 컴파일러는 클래스를 컴파일할 때 다음 네 가지 함수들이 존재하는지 체크해 존재하지 않으면, 이러한 암묵적은 생성은 1) 편의를 위한 것이자, 2) C와의 하위 호환성을 위한 것이다. C++에서 C 스타일의 struct는 오직 public 자료 멤버들로만 이루어진 일종의 클래스이다. 그래도 그런 구조체를 생성하고, 복사하고, 파괴할 수 있어야 하기 때문에, C++ 언어는 그런 구조체에
대해 그리고, 이들이 실제 사용되는 코드가 존재할 때 이들을 정의한다. 그럼 암묵적으로 생성되는 네 가지 함수들에 대해 하나씩 자세히 정리해 보자.
1. 기본 생성자 프로그래머가 기본 생성자를 명시적으로 선언하지 않으면, 하나의 기본 생성자가 암묵적으로 생성된다.
2. 복사 생성자 프로그래머가 복사 생성자를 명시적으로 선언하지 않으면, 하나의 복사 생성자가 암묵적으로 생성된다. 기본적으로는 아래와 같은 시그너쳐를 가진다.
위에서 가능한 경우에 const 참조로 매개변수를 받는다고 했다.
그리고 행여나 포인터 객체로 생성해놓구선 복사 생성자나 대입 연산자를 쓰진 않겠지? ㅡ,.ㅡ? 3. 대입 연산자 프로그래머가 대입 연산자를 명시적으로 선언하지 않으면, 하나의 대입 연산자가 암묵적으로 생성된다.
살짝 다른 얘기로 빠져서...아래의 예를 보자.
위 예제에서 1번과 2번 지점에서 각각 어떤 함수가 호출되나? 이건 헤깔리면 안 된다. 객체가 생성되는 과정에서의 = 연산은 복사 생성자를 호출한다.그리고 이미 생성된 객체들간에 = 연산이 사용될 때는 대입 연산자가 호출되는 것이다. 4. 소멸자 프로그래머가 소멸자 함수를 명시적으로 선언하지 않으면, 하나의 소멸자가 암묵적으로 생성된다.
즉, 소멸자 안에서 예외가 발생하면 그 안에서 처리가 되어야지 다른 곳으로 전파가 되면 안 된다는 뜻이다. 이를 내버려 두면, 시한폭탄이나 마찬가지라서 프로그램의 종료 후 이상 증세를 일으킬 수 있다. 이에 대해선 Effective C++ 3판, 챕터9를 한 번 읽어보는 것이 좋다. 고수 질문 모든 파생클래스들이 하나 이상의 암묵적으로 선언, 정의된 함수들을 사용하지 않도록 강제하고 싶은 기반 클래스가 있다.
Count 기반 클래스 작성자가 친절하게 주석까지 달아 놓았지만, 파생 클래스 작성자들이 지키리라는 보장은 어디에도 없다.
이 예제에서,
Count의 저자가 파생 클래스가 올바르게 작성되도록 하려면, Count 클래스가 어떻게 변경되어야 할까? 좀 더 자세하게 얘기해서, 컴파일러가 암묵적으로 생성시키는 네 가지 함수를 어떻게든 올바르게 작성하게 강제할 수 있을까? Count 클래스는 명시한 특수 형태의 생성자만 사용해야 하고, 어떤 식으로든 복사도 허용하지 않는 것이 주요 원칙이다.(이런 식의 요구 조건들은 보통 개체 수를 한정짓는 Singleton 패턴에서 흔히 볼 수 있다) 이를 달성하기 위해서는 다음과 같은 장치들이 마련되어 있어야 한다. 1. 기본 생성자 허용
금지 기본 생성자 허용 금지는 의외로 간단하다. 기반 클래스에 기본 생성자가 존재하지 않기 때문에,
복사 금지 역시 어렵지 않다. 기반 클래스에서 복사 생성자와 대입 연산자를 private 영역에 두고 선언만 해 두면,
이제 Count 클래스를 원래 목적에 맞게 최종 수정하면 다음과 같은 형태가 된다.
원하는 기능을 모두 파생 클래스에서 할 수 없도록 하였으며, 파생된 클래스들이 암묵적으로 생성되는 함수들을 사용하지 못하게 하는 가장 간단하고도 최선의 선택은 |