rein's world

C++에는 final 키워드가 있는가?

Java 프로그래밍 언어를 처음 접한게 아마 학부 1학년 2학기의 컴퓨터 프로그래밍 수업이었던 것 같다. 당시 Java의 기능 중에 마음에 들었던 것이 final 키워드의 존재였다.

Java의 final 키워드는 해당 함수를 static 하게 바인딩(binding)하게 해주거나, 상속받지 못하게 하거나 등등의 역할을 하는데, 주목했던 부분은 바로 상속을 금지하는 것. C++의 특성상, 특정 class를 상속받지 못하게하는게 필요할 때가 있다. 예를 들어서 virtual function table (가상 함수 테이블; 일명 vtable) 포인터를 위한 포인터 공간이 아까워서(매우 작은 데이터 클래스가 필요한 경우) 이러는 경우도 있고, 라이브러리의 요구사항에 의해서 그런 경우도 있을 수 있다. 그렇지만 C++의 키워드만으로는 혹은 boost::noncopyable 같이 간단한 방법으로는 이 문제를 해결할 수 없다.

그렇다면 어떤 방법으로 해결해야하는가? C++의 아버지인 Bjarne Stroustrup이 조금 복잡한 우회 방법을 하나 제시하고 있다. class DontWantDerivation 이라는 class가 상속이 되지 않게하려면 다음과 같은 클래스가 하나 필요하다.

class DontWantDerivation; // forward declaration

class Trick    friend class DontWantDerivation;
    private: Trick() { } Trick( const Trick& ) { }
};

class DontWantDerivation : public virtual Trick { // class 선언 };

감이 오는가?

Trick이라는 class에서 friend class인 DontWantDerivation (이 class만 상속되지 않으면된다)을 friend class로 선언해서 private 생성자들에게 접근하게 해주고, DontWantDerivation은 Trick을 가상 상속(virtual inheritance)로 상속받아서, DontWantDerivation을 상속받으려면 상속 받은 class가 Trick에 생성자에 접근하게 만드는데, 그런 일은 불가능하므로(private이니) DontWantDerivation class를 상속받을 수 없다 :D

조금(?) 예쁘지 않은 방법이고, boost::noncoypable 처럼 예쁘게 사용하는 것도 불가능하다. Template 을 써서 어떻게 포장해볼 수 있을까 했는데 잘 안되는 것 같다. 사실 Java에선 상속 금지보다는, Java에서 기본이 아닌 static binding을 통해 성능을 올려보자라는 측면이 강한 것 같고, C++에선 이런 종류의 성능 문제는 없기 때문에 – 기본이 static binding이다 – 이런 키워드도 없긴하다. 그러니 일단 있는 것으로 잘 살아가봐야겠지 Orz