[C++] 4.2 클래스 - 복사 생성자

씹어먹는 C++ 강좌 따라하는 노트입니다.


new Class, delete Class[n]

윷놀이, 재기차기, 화투와 같은 한국 전통 민속놀이인 스타크래프트1의 마린을 C++로 구현해봅시다.

#include <iostream>

class Marine {
	int hp;						// 마린 체력
	int coord_x, coord_y;		// 마린 위치
	int damage;					// 공격력
	int is_dead;			

public:
	Marine();					// 기본 생성자
	Marine(int x, int y);		// x, y 좌표에 마린 생성

	int attack();				// x, y 좌표에 마린 생성
	void be_attacked(int damage_earn);	//입는 데미지
	void move(int x, int y);	// 새로운 위치

	void show_status();			// 상태 띄우기
};
Marine::Marine(){
	hp = 50;
	coord_x = coord_y = 0;
	damage = 5;
	is_dead = false;
}
Marine::Marine(int x, int y){
	coord_x = x;
	coord_y = y;
	hp = 50;
	damage = 5;
	is_dead = false;
}
void Marine::move(int x, int y){
	coord_x = x;
	coord_y = y;
}
int Marine::attack(){
	return damage;
}
void Marine::be_attacked(int damage_earn){
	hp -= damage_earn;
}
void Marine::show_status(){
	std::cout << "** Marine **" << std::endl;
	std::cout << " Loacation : ( " << coord_x << ", " << coord_y << ")" << std::endl;
	std::cout << " HP : " << hp << std::endl;
}

int main(){
	Marine marine1(2,3);
	Marine marine2(3,5);

	marine1.show_status();
	marine2.show_status();

	std::cout << std::endl << "마린 1 이 마린 2 를 공격!" << std::endl;
	marine2.be_attacked(marine1.attack());

	marine1.show_status();
	marine2.show_status();
}

  • 마린1 이 마린2를 공격하는 코드이다.

마린을 저런식으로 하나하나 만드는건 힘들다. 그럼 new를 사용해서 만들어보자.

int main(){
	Marine * marine[100];

	marine[0] = new Marine(2,3);
	marine[1] = new Marine(3,5);

	marine[0]->show_status();
	marine[1]->show_status();

	std::cout << std::endl << "마린 1 이 마린 2 를 공격" << std::endl;
	marine[1]->be_attacked(marine[0]->attack());

	marine[0]->show_status();
	marine[1]->show_status();
    
    delete marine[0];
	delete marine[1];
}

  • 결과는 똑같다.
  • new는 malloc과 메모리 할당을 시켜주는건 같은데, 조금 다름
    • 클래스 생성자를 부를 수 있다는 점에서 다름.
    • C와 C++의 가장 큰 차이점이라고 볼 수 있음.
  • new 를 했으면 delete 도 꼭 해줘야한다.

소멸자

마린에게 이름을 부여해주고 컴파일을 해보자.

class Marine {
	int hp;						// 마린 체력
	int coord_x, coord_y;		// 마린 위치
	int damage;					// 공격력
	char * name;				// 이름
	int is_dead;			

public:
	Marine();					// 기본 생성자
	Marine(int x, int y);		// x, y 좌표에 마린 생성
	Marine(int x, int y, const char* marine_name);		// x, y 좌표에 이름을 가진 마린 생성

	int attack();				// x, y 좌표에 마린 생성
	void be_attacked(int damage_earn);	//입는 데미지
	void move(int x, int y);	// 새로운 위치

	void show_status();			// 상태 띄우기
};
Marine::Marine(){
	hp = 50;
	coord_x = coord_y = 0;
	damage = 5;
	name = NULL;
	is_dead = false;
}
Marine::Marine(int x, int y){
	coord_x = x;
	coord_y = y;
	hp = 50;
	damage = 5;
	name = NULL;
	is_dead = false;
}
Marine::Marine(int x, int y, const char* name){
	coord_x = x;
	coord_y = y;
	hp = 50;
	damage = 5;
	name = new char[strlen(name) +1];
	is_dead = false;
}

...

  • 결과가 잘 나온다.
  • name = new char[strlen(name) +1];
    근데 클래스 내에서 메모리를 부여해놓고 delete 하는 코드도 없이 사용해버렸다.
  • 이렇게 되면 메모리 누수문제가 발생한다.
  • C++에서는 이런 일을 방지하기위해 '소멸자(Destructor)' 라는 것을 지원한다.

소멸자를 사용해보자.

class Marine {
	int hp;						// 마린 체력
	int coord_x, coord_y;		// 마린 위치
	int damage;					// 공격력
	char * name;				// 이름
	int is_dead;			

public:
	Marine();					// 기본 생성자
	Marine(int x, int y);		// x, y 좌표에 마린 생성
	Marine(int x, int y, const char* marine_name);		// x, y 좌표에 이름을 가진 마린 생성
	~Marine();					// 소멸자

	int attack();				// x, y 좌표에 마린 생성
	void be_attacked(int damage_earn);	//입는 데미지
	void move(int x, int y);	// 새로운 위치

	void show_status();			// 상태 띄우기
};
Marine::Marine(){
	hp = 50;
	coord_x = coord_y = 0;
	damage = 5;
	name = NULL;
	is_dead = false;
}
Marine::Marine(int x, int y){
	coord_x = x;
	coord_y = y;
	hp = 50;
	damage = 5;
	name = NULL;
	is_dead = false;
}
Marine::Marine(int x, int y, const char* marine_name){
	coord_x = x;
	coord_y = y;
	hp = 50;
	damage = 5;
	name = new char[strlen(marine_name) +1];
	strcpy(name, marine_name);
	is_dead = false;
}
Marine::~Marine() {
  std::cout << name << " 의 소멸자 호출 ! " << std::endl;
  if (name != NULL) {
    delete[] name;
  }
}

  • 소멸자를 사용하여 결과를 확인해보니, 클래스 삭제시 자동으로 소멸자가 호출되는 것을 확인할 수 있다.
  • delete 시 꼭 소멸자를 사용해야하는 클래스(메모리를 추가적으로 사용한 클래스) 를 소멸시킬땐 위와 같이 delete 클래스[n]으로 어느클래스를 삭제할지 꼭 정해줘야한다.

소멸자가 필요가 없으면 안써줘도 되고, 안써줘도 Default소멸자가 있다.

좋은 웹페이지 즐겨찾기