#include <string.h>
#include <iostream>
class Marine {
int hp; // 마린 체력
int coord_x, coord_y; // 마린 위치
int damage; // 공격력
bool is_dead;
char* name; // 마린 이름
public:
Marine(); // 기본 생성자
Marine(int x, int y, const char* marine_name); // 이름까지 지정
Marine(int x, int y); // x, y 좌표에 마린 생성
~Marine();
int attack(); // 데미지를 리턴한다.
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;
name = NULL;
}
Marine::Marine(int x, int y, const char* marine_name) {
name = new char[strlen(marine_name) + 1];
strcpy(name, marine_name);
coord_x = x;
coord_y = y;
hp = 50;
damage = 5;
is_dead = false;
}
Marine::Marine(int x, int y) {
coord_x = x;
coord_y = y;
hp = 50;
damage = 5;
is_dead = false;
name = NULL;
}
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;
if (hp <= 0) is_dead = true;
}
void Marine::show_status() {
std::cout << " *** Marine : " << name << " ***" << std::endl;
std::cout << " Location : ( " << coord_x << " , " << coord_y << " ) "
<< std::endl;
std::cout << " HP : " << hp << std::endl;
}
Marine::~Marine() {
std::cout << name << " 의 소멸자 호출 ! " << std::endl;
if (name != NULL) {
delete[] name;
}
}
int main() {
Marine* marines[100];
marines[0] = new Marine(2, 3, "Marine 2");
marines[1] = new Marine(1, 5, "Marine 1");
marines[0]->show_status();
marines[1]->show_status();
std::cout << std::endl << "마린 1 이 마린 2 를 공격! " << std::endl;
marines[0]->be_attacked(marines[1]->attack());
marines[0]->show_status();
marines[1]->show_status();
delete marines[0];
delete marines[1];
}
new
객체를 동적으로 생성하면서와 동시에 자동으로 생성자도 호출한다.
리턴하는 것이 바로 생성된 객체의 주소값, 따라서 & 를 붙일 필요가 없다
class 내부에 있는 const
클래스 안에 멤버 변수와 함수들한테 const를 붙임으로써 해당 함수에서 객체의 멤버를 변경할 수 없도록 한다
마린 이름만들때 name 그리고 Marines *marines[100] 에서 포인터를 사용한 이유
마린 객체를 동적으로 생성하기 위함
name = new char [strlen(pc.name) + 1]
이 부분에서 +1을 하는 이유 = 널문자 \0을 넣기 위해서이다.
name 은 그냥 일반 포인터이므로 sizeof(name) 을 찍어보면 배열의 크기가 아니라 4 가 나올 것.
\따라서 + 1 을 전달해야 한다.
생성자는 어떤 객체가 생성과 동시에 유효함을 보장하는 역할을 한다.
class Person {
int age;
int height;
}
Person p = new Person();
현재 Person p는 나이가 0 이고 키도 0 입니다. 이런 사람은 존재할 수 없겠죠? 그래서 이런 객체는 유효하지 않다고 합니다. 이 문제를 해결하기 위해 생성자를 이용합니다.
Marine(int x, int y); 처럼 마린을 생성하는 함수가 있는데 따로
Marine::Marine() {
hp = 50;
coord_x = coord_y = 0;
damage = 5;
is_dead = false;
}
라는 기본생성자를 생성해줘야 하는 이유는 기본 생성자를 정의하지 않으면 컴파일러가 알아서 하나 만들어주는데 (디폴트 생성자), 이 생성자는 데이터 멤버들을 디폴트로 초기화 해줍니다. 예를들어 위 경우 hp 나 damage 가 모두 0 이 됩니다.
(난이도 : 中)
#include <iostream>
class string {
char* str;
int len;
public:
string(char c, int n); // 문자 c 가 n 개 있는 문자열로 정의
string(const char* s);
string(const string& s);
~string();
void add_string(const string& s); // str 뒤에 s 를 붙인다.
void copy_string(const string& s); // str 에 s 를 복사한다.
int strlen(); // 문자열 길이 리턴
void print();
};
string::string(char c, int n) {
len = n;
str = new char[len];
for (int i = 0; i < len; i++) {
str[i] = c;
}
str[len] = NULL;
}
string::string(const char* s) {
len = 0;
while (s[len]) {
len++;
}
str = new char[len];
for (int i = 0; i < len; i++) {
str[i] = s[i];
}
}
string::string(const string& s) {
len = s.len;
str = new char[len];
for (int i = 0; i < len; i++) {
str[i] = s.str[i];
}
}
string::~string() {
if (str) {
delete[] str;
}
}
void string::add_string(const string& s) {
char* tmp = new char[len + s.len];
int i;
for (i = 0; i < len; i++) tmp[i] = str[i];
for (int j = 0; i < len + s.len; i++, j++) tmp[i] = s.str[j];
len += s.len, delete[] str, str = tmp;
}
void string::copy_string(const string& s) {
len = s.len;
delete[] str;
str = new char[len];
for (int i = 0; i < len; i++) {
str[i] = s.str[i];
}
}
int string::strlen() {
return len;
}
void string::print()
{
for (int i = 0; i < len; i++) std::cout << str[i];
}
int main() {
string str1("ABCEDFGHIJKL");
string str2(str1);
string add("mnopqrstuvwxyz");
str1.print(), std::cout << std::endl, str2.print(), std::cout << std::endl;
add.print(), std::cout << std::endl;
std::cout << str1.strlen() << ", " << add.strlen() << std::endl;
str1.add_string(add);
str2.copy_string(str1);
str1.print(), std::cout << std::endl, str2.print(), std::cout << std::endl;
std::cout << str1.strlen() << ", " << str2.strlen() << std::endl;
return 0;
}
씹어먹는 C++ - <4 - 3. 스타크래프트를 만들자 ① (복사 생성자, 소멸자)>
생성자를 만드는 이유가 먼가요?