본문 바로가기
번역/Bjarne Stroustrup's C++ Style and Technique FAQ

Can I stop people deriving from my class?

by 겜게준 2019. 2. 27.

다른 사람이 제 클래스를 파생하는것을 막을 수 있나요?


할 수 있는데 왜 할려고 하나요? 일반적인 답변 두 가지가 있습니다 :


효율을 위해 : 자신의 함수 호출이 virtual 인 것을 피하기 위해

안전을 위해 :자신의 클래스가 기본 클래스로 쓰이지 않는다는 것을 보증하기 위해 (예를 들자면, 슬라이싱에 대한 걱정 없이 객체를 복사하는 것을 틀림없이 하기 위해)


제 경험상, 효율의 문제라면 보통 쓸때없는 걱정입니다. C++에서는, 가상 함수 호출은 아주 빠르기 때문에 가상 함수로 설계된 클래스를 실제 사용했을 때, 일반적인 함수 호출을 사용하는 대안책과 비교하여 측정할 수 있는 런타임 오버헤드를 만들지 않습니다. 여기서 중요한 것은 가상 함수 호출 메커니즘은 전형적으로 포인터나 참조에 의한 호출에서만 사용됩니다. 이름이 지정된 오브젝트로 직접 함수를 호출했을 때, 가상 함수 클래스의 오버헤드는 쉽게 최적화됩니다.


가상 함수 호출을 피하기 위해 클래스 구조를 "capping" 해야 할 진짜 이유가 있다면, 왜 처음부터 가상 함수였는지 묻고 싶습니다. 성능상 중요한 기능들이 좋은 이유 없이 virtual로 만들어 졌던 예를 봤고, 단지 그것이 "우리가 평소에 하던 방식"이기 때문이었습니다.


논리적인 이유로 파생을 방지하는 방법인 이 문제의 다른 변형(?)은 c++11에 해결책이 있습니다.


struct Base {

virtual void f();

};


struct Derived final : Base { // now Derived is final; you cannot derive from it

void f() override;

};


struct DD: Derived {// error: Derived is final


// ...

};


오래된 컴파일러 에서는 지저분한 방식을 사용할 수 있습니다.


class Usable;


class Usable_lock {

friend class Usable;

private:

Usable_lock() {}

Usable_lock(const Usable_lock&) {}

};


class Usable : public virtual Usable_lock {

// ...

public:

Usable();

Usable(char*);

// ...

};


Usable a;


class DD : public Usable { };


DD dd;  // 에러: DD::DD()에 접근할 수 없습니다.

// Usable_lock::Usable_lock(): private 멤버입니다.

댓글