본문 바로가기
프로그래밍/C++

가상 복사 생성자

by 리뷰하는 (게임)프로그래머_리프TV 2010. 4. 3.



상황에 따라서 새로 생성한 이 후 그 내용을 복사해 주고 싶다면 어떻게 할까?

가상 복사 생성자,

어디서 뭘 설명해야 할지 모르겠지만,

객체 포인터 배열 A와
객체 포인터 배열 B가 존재 한다고 했을 때

A에 값을 삽입 후

B = A; 를 해주었을 때

B에 A의 내용이 그대로 복사 되길 원한다고 하자.

그때 사용한다.

나머진 소스 코드로 ㅠㅠ

#include <iostream>

class Mammal
{
protected:
	int itsAge;
public:
	Mammal() : itsAge(1) { std::cout << "Mammal 생성자" << std::endl; }
	virtual ~Mammal() { std::cout << "Mammal 소멸자" << std::endl; }

	int GetAge() { return itsAge; }

	Mammal( const Mammal& rhs );
	virtual void Speak() const { std::cout << "Mammal speack!" << std::endl; }

	virtual Mammal* Clone() 
	{
		std::cout << this << std::endl;
		return new Mammal(*this); 
	}
	// 복사 생성자를 호출해서 새로운 객체를 heap에 만든 후 그 객체의 주소를 반환.
};

// 객체 레퍼런스를 인자로 받고 있다.
Mammal::Mammal( const Mammal& rhs )
:itsAge(rhs.itsAge)
{
	std::cout << "Mammal 복사 생성자" << std::endl;
}

class Dog : public Mammal
{
public:
	Dog() { std::cout << "Dog 생성자" << std::endl; }
	~Dog() { std::cout << "Dog 소멸자" << std::endl; }

	Dog( const Dog& rhs );

	void Speak() const { std::cout << "멍멍" << std::endl; }
	// Clone() 호출 시 똑같은 객체를 힙에 생성해서 주소값을 return
	virtual Mammal * Clone() 
	{
		std::cout << this << std::endl;
		return new Dog(*this); 
	}
};

Dog::Dog(const Dog &rhs)
:Mammal(rhs)
{
	// clone에서 넘어온 this를 객체 레퍼런스로 
	std::cout << "Dog 복사 생성자" << std::endl;
}

class Cat : public Mammal
{
public:
	Cat() {std::cout << "Cat 생성자" << std::endl; }
	~Cat() { std::cout << "Cat 소멸자" << std::endl; }

	Cat( const Cat& rhs );

	void Speak() const { std::cout << "냐옹" << std::endl; }
	virtual Mammal* Clone() 
	{
		std::cout << this << std::endl;
		return new Cat(*this);
	}
};

Cat::Cat( const Cat& rhs )
:Mammal(rhs)
{
	std::cout << "Cat 복사 생성자" << std::endl;
}

enum ANIMALS { MAMMAL, DOG, CAT };

const int NumAnimalType = 3;

void main()
{
	// Mammal의 객체 포인터 배열 생성,
	Mammal* theArray[NumAnimalType];

	int choice;

	for( int i=0; i<NumAnimalType; i++ )
	{
		std::cout << "1 Dog, 2 Cat, 그외 Mammal" << std::endl;
		std::cin >> choice;

		switch(choice)
		{
		case DOG: 
			theArray[i] = new Dog;
			break;
		case CAT:
			theArray[i] = new Cat;
			break;
		default:
			theArray[i] = new Mammal;
			break;
		}
	}

	// 복사가 이루어질 객체 포인터 배열
	Mammal* otherArray[NumAnimalType];

	std::cout << std::endl << "theArray[i]->Speak()" << std::endl;

	// 기존의 객체 포인터 배열에서 소리를 질러보고
	for( int i=0; i<NumAnimalType; i++ )
	{
		theArray[i]->Speak();
	}

	// 그 내용을 복사한다.
	for( int i=0; i<NumAnimalType; i++ )
	{
		// theArray의 주소는 clone안의 this와 동일
		std::cout << theArray[i] << std::endl;
		otherArray[i] = theArray[i]->Clone();
	}

//	이거랑 같은 뜻, 결국 복사 생성자에서 복사를 해주는 것과 같다.
//	Mammal a;
//	Mammal b(a);
//	단지 새로 할당하여 집어 넣는다는것 빼면 어려울게 없다.

	std::cout << std::endl << "otherArrey[i]->Spack()" << std::endl;

	// 복사 된것을 확인 할 수 있다.
	for( int i=0; i<NumAnimalType; i++ )
	{
		otherArray[i]->Speak();
	}

	// 메모리 해제
	for( int i=0; i<NumAnimalType; i++ )
	{
		delete [] otherArray[i];
		delete [] theArray[i];
	}
}​

'프로그래밍 > C++' 카테고리의 다른 글

연산자 오버로딩(operator overlonding)(2)  (0) 2010.04.04
연산자 오버로딩(operator overloading)(1)  (0) 2010.04.04
virtual(가상)  (0) 2010.04.03
함수 오버라이딩(overriding)  (0) 2010.04.03
객체 레퍼런스  (0) 2010.04.03