C++ 언어에서는 '가상 생성자'라는 개념이 직접적으로 존재하지 않지만, 런타임에만 알려지는 유형으로 파생 클래스 객체의 인스턴스를 만들어야 하는 필요성은 자주 발생합니다. 이와 같은 작업은 역사적으로 가상 함수 — 일반적으로 'clone()' 또는 'create()' 패턴을 통해 '가상 생성자' 패턴으로 해결됩니다.
문제의 역사: C++의 초기 버전부터 생성자가 가상으로 선언될 수 없다는 제약이 있었습니다. 그럼에도 불구하고 클래스 계층에서 기존 객체를 기반으로 새로운 객체를 생성해야 할 경우가 종종 발생합니다.
문제: 전통적으로 생성자는 어떤 가상 함수 메커니즘에도 따르지 않으므로 호출이 항상 컴파일 단계에서 결정됩니다. 이는 기본 클래스 생성자를 통해 시간에 따라 실제 유형을 가진 생성 객체에 대한 '실시간' 팩토리를 얻을 수 없음을 의미합니다.
해결책: 기본 클래스에서 가상 함수를 구현하는 것이 좋습니다 — 일반적으로 이는 clone() (객체의 복사본 생성) 또는 create() (상태를 복사하지 않고 동일한 유형의 객체 생성)를 의미합니다.
코드 예시:
class Base { public: virtual ~Base() {} virtual Base* clone() const = 0; }; class Derived : public Base { public: Derived(int v) : value(v) {} Base* clone() const override { return new Derived(*this); } private: int value; }; void process(const Base& b) { Base* b2 = b.clone(); // 가상 메소드를 통해 올바른 복사본을 생성 delete b2; }
주요 특징:
C++에서 생성자를 virtual로 선언할 수 있나요?
아니요, C++의 문법은 생성자에 대해 virtual 수식어를 허용하지 않습니다. 그렇지 않으면 컴파일러가 컴파일 오류를 발생시킵니다.
clone()을 직접 선언한다면, 기본 클래스에서 반드시 순수 가상으로 만들어야 하나요?
아니요, 반드시 그럴 필요는 없습니다. 상태의 일부만 복사하거나 nullptr를 반환할 의미가 있다면 clone()에 기본 구현을 제공할 수 있지만, 일반적으로 더 많은 제어를 위해 순수 가상 함수(pure virtual)로 설정합니다.
팩토리 정적 메서드를 clone() 대체로 사용할 수 있나요? 가상성과는 어떻게 연결되나요?
정적 팩토리 메서드는 가상의 기능이 아니며 클래식한 방식으로 자식에서 재정의되지 않습니다. 진정한 '가상 생성자'를 위해서는 인스턴스의 가상 함수나 다른 동적 유형 결정 방법이 필요합니다.
개발자가 정적 메서드를 통해 패턴을 구현했습니다:
class Base { public: static Base* create() { return new Base; } }; class Derived : public Base {}; // ... Base::create()가 호출되어 Base를 반환, 실제 유형 정보 손실
장점:
단점:
코드는 clone()을 사용합니다:
class Base { public: virtual ~Base() {} virtual Base* clone() const = 0; }; class Derived : public Base { int x; public: Derived(int x) : x(x) {} Base* clone() const override { return new Derived(*this); } };
장점:
단점: