1. 가상 복사 생성자의 개념
이전 가상 생성자 글에서 런타임까지 유형이 결정되지 않는 객체를 생성하는 방법을 살펴봤다. 객체가 정확한 클래스 유형인지 알지 못한 채 생성하는 것이 가능할까? 여기서 등장하는 것이 바로 가상 복사 생성자다. 이것이 이 문제를 해결한다.
간혹 우리는 기존의 다른 객체로부터 객체를 구성해야 할 필요가 있을 수 있다. 그리고 엄밀히 말하면, 복사 생성자가 같은 일을 한다. 새로운 객체의 초기 상태는 기존의 다른 객체 상태를 기반으로 한다. 컴파일러는 객체가 다른 객체로부터 인스턴스화될 때 복사 생성자를 호출한다. 그러나 컴파일러는 적절한 복사 생성자를 호출하기 위해 구체적인 유형 정보가 필요하다.
예시:
#include <iostream>
using namespace std;
class Base
{
public:
//
};
class Derived : public Base
{
public:
Derived()
{
cout << "Derived created" << endl;
}
Derived(const Derived &rhs)
{
cout << "Derived created by deep copy" << endl;
}
~Derived()
{
cout << "Derived destroyed" << endl;
}
};
int main()
{
Derived s1;
Derived s2 = s1; // Compiler invokes "copy constructor"
// Type of s1 and s2 are concrete to compiler
// How can we create Derived1 or Derived2 object
// from pointer (reference) to Base class pointing Derived object?
return 0;
}
어떤 종류의 객체에서 복사 구성을 할지 결정할 수 없다면 어떻게 될까? 예를 들어, 가상 생성자는 어떤 입력을 기반으로 런타임에 클래스 계층 구조의 객체를 만든다. 가상 생성자가 만든 다른 객체에서 객체를 복사하려고 할 때, 일반적인 복사 생성자를 사용할 수 없다. 런타임에 객체를 복제할 수 있는 특별한 복제 기능이 필요하다.
예를 들어, 도면 응용 프로그램을 생각해 보자. 캔버스에 이미 그려진 객체를 선택하여 동일한 객체의 인스턴스를 하나 더 붙여넣을 수 있다. 그런데 어떤 객체를 복붙할지 결정할 수 없다. 우리는 여기서 도움을 줄 가상 복사 생성자가 필요한 것이다.
예시:
#include <iostream>
using namespace std;
//// LIBRARY START
class Base
{
public:
Base() { }
virtual // Ensures to invoke actual object destructor
~Base() { }
virtual void ChangeAttributes() = 0;
// The "Virtual Constructor"
static Base *Create(int id);
// The "Virtual Copy Constructor"
virtual Base *Clone() = 0;
};
class Derived1 : public Base
{
public:
Derived1()
{
cout << "Derived1 created" << endl;
}
Derived1(const Derived1& rhs)
{
cout << "Derived1 created by deep copy" << endl;
}
~Derived1()
{
cout << "~Derived1 destroyed" << endl;
}
void ChangeAttributes()
{
cout << "Derived1 Attributes Changed" << endl;
}
Base *Clone()
{
return new Derived1(*this);
}
};
class Derived2 : public Base
{
public:
Derived2()
{
cout << "Derived2 created" << endl;
}
Derived2(const Derived2& rhs)
{
cout << "Derived2 created by deep copy" << endl;
}
~Derived2()
{
cout << "~Derived2 destroyed" << endl;
}
void ChangeAttributes()
{
cout << "Derived2 Attributes Changed" << endl;
}
Base *Clone()
{
return new Derived2(*this);
}
};
class Derived3 : public Base
{
public:
Derived3()
{
cout << "Derived3 created" << endl;
}
Derived3(const Derived3& rhs)
{
cout << "Derived3 created by deep copy" << endl;
}
~Derived3()
{
cout << "~Derived3 destroyed" << endl;
}
void ChangeAttributes()
{
cout << "Derived3 Attributes Changed" << endl;
}
Base *Clone()
{
return new Derived3(*this);
}
};
// We can also declare "Create" outside Base.
// But is more relevant to limit it's scope to Base
Base *Base::Create(int id)
{
// Just expand the if-else ladder, if new Derived class is created
// User need not be recompiled to create newly added class objects
if( id == 1 )
{
return new Derived1;
}
else if( id == 2 )
{
return new Derived2;
}
else
{
return new Derived3;
}
}
//// LIBRARY END
//// UTILITY SRART
class User
{
public:
User() : pBase(0)
{
// Creates any object of Base hierarchy at runtime
int input;
cout << "Enter ID (1, 2 or 3): ";
cin >> input;
while( (input != 1) && (input != 2) && (input != 3) )
{
cout << "Enter ID (1, 2 or 3 only): ";
cin >> input;
}
// Create objects via the "Virtual Constructor"
pBase = Base::Create(input);
}
~User()
{
if( pBase )
{
delete pBase;
pBase = 0;
}
}
void Action()
{
// Duplicate current object
Base *pNewBase = pBase->Clone();
// Change its attributes
pNewBase->ChangeAttributes();
// Dispose the created object
delete pNewBase;
}
private:
Base *pBase;
};
//// UTILITY END
//// Consumer of User (UTILITY) class
int main()
{
User *user = new User();
user->Action();
delete user;
}
가상 생성자의 도움을 받아 객체를 생성하는 사용자 클래스를 볼 수 있다. 생성할 객체는 사용자 입력을 기반으로 한다. Action()은 생성 중인 객체를 복제하고, 그 객체의 속성을 수정하는 것이다. 복제된 객체는 가상 복사 생성자로도 간주되는 Clone() 가상 함수의 도움을 받아 생성된다. Clone() 메서드 뒤에 있는 개념은 프로토타입 패턴의 빌드 블록이다.
'C++' 카테고리의 다른 글
C++ 순수 가상 함수와 추상 클래스 총정리 (0) | 2024.04.15 |
---|---|
C++ 순수 가상 소멸자(Pure Virtual Destructor) 총정리 (1) | 2024.04.12 |
C++ 가상 생성자(Virtual Constructor) 총정리 (0) | 2024.04.08 |
C++ 가상 소멸자(Virtual Destructor) 총정리 (0) | 2024.04.08 |
C++ 인라인(Inline) 함수 총정리 (0) | 2024.04.04 |