[C++] const, static
위 링크에서 공부한 내용 정리입니다.
생성자의 초기화 리스트
class Marine {
int hp; // 마린 체력
int coord_x, coord_y; // 마린 위치
int damage; // 공격력
bool is_dead;
public:
Marine(); // 기본 생성자
Marine(int x, int y); // x, y 좌표에 마린 생성
int attack(); // 데미지를 리턴한다.
void be_attacked(int damage_earn); // 입는 데미지
void move(int x, int y); // 새로운 위치
void show_status(); // 상태를 보여준다.
};
Marine::Marine() : hp(50), coord_x(0), 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) {}
위 코드에서
Marine::Marine() : hp(50), coord_x(0), 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) {}
해당 코드들을 생성자 초기화 리스트라고 한다
(생성자 이름) : var1(arg1), var2(arg2) {}
일반적인 꼴은 위와 같다
디폴트 생성자와 생성자 초기화 리스트의 차이
- 생성자 초기화 리스트: 생성과 초기화를 동시에
- 디폴트 생성자: 생성을 먼저하고 그 다음에 대입
// 생성자 초기화 리스트
int a = 10;
// 디폴트 생성자
int a;
a = 10;
이런 느낌이라고 한다
생성과 동시에 초기화 되어야 하는 것
- 상수
- 레퍼런스
상수와 레퍼런스는 모두 생성과 동시에 초기화되어야 하며, 그렇지 않으면 컴파일 오류가 난다
#include <iostream>
class Marine {
int hp; // 마린 체력
int coord_x, coord_y; // 마린 위치
bool is_dead;
const int default_damage; // 기본 공격력
public:
Marine(); // 기본 생성자
Marine(int x, int y); // x, y 좌표에 마린 생성
int attack(); // 데미지를 리턴한다.
void be_attacked(int damage_earn); // 입는 데미지
void move(int x, int y); // 새로운 위치
void show_status(); // 상태를 보여준다.
};
Marine::Marine()
: hp(50), coord_x(0), coord_y(0), default_damage(5), is_dead(false) {}
Marine::Marine(int x, int y)
: coord_x(x), coord_y(y), hp(50), default_damage(5), is_dead(false) {}
default_damage가 const여서 생성과 동시에 초기화해주는 모습이다
const는 한번 초기화 되면 값을 바꿀 수 없다
Marine::Marine(int x, int y, int default_damage)
: coord_x(x),
coord_y(y),
hp(50),
default_damage(default_damage),
is_dead(false) {}
이런식으로 생성할 때 값을 전달 받아서 초기화 할 수도 있다
const int default_damage = (인자로 받은 default_damage);
위에 코드는 이걸 실행하는 것과 똑같다고 한다
static 변수
전역 변수 같지만 클래스 하나에만 종속되는 변수
// static 멤버 변수의 사용
#include <iostream>
class Marine {
static int total_marine_num;
int hp; // 마린 체력
int coord_x, coord_y; // 마린 위치
bool is_dead;
const int default_damage; // 기본 공격력
public:
Marine(); // 기본 생성자
Marine(int x, int y); // x, y 좌표에 마린 생성
Marine(int x, int y, int default_damage);
int attack(); // 데미지를 리턴한다.
void be_attacked(int damage_earn); // 입는 데미지
void move(int x, int y); // 새로운 위치
void show_status(); // 상태를 보여준다.
~Marine() { total_marine_num--; }
};
int Marine::total_marine_num = 0;
Marine::Marine()
: hp(50), coord_x(0), coord_y(0), default_damage(5), is_dead(false) {
total_marine_num++;
}
Marine::Marine(int x, int y)
: coord_x(x), coord_y(y), hp(50), default_damage(5), is_dead(false) {
total_marine_num++;
}
Marine::Marine(int x, int y, int default_damage)
: coord_x(x),
coord_y(y),
hp(50),
default_damage(default_damage),
is_dead(false) {
total_marine_num++;
}
void create_marine() {
Marine marine3(10, 10, 4);
marine3.show_status();
}
int main() {
Marine marine1(2, 3, 5);
marine1.show_status();
Marine marine2(3, 5, 10);
marine2.show_status();
create_marine();
std::cout << std::endl << "마린 1 이 마린 2 를 공격! " << std::endl;
marine2.be_attacked(marine1.attack());
marine1.show_status();
marine2.show_status();
}
여기서 create_marine()에서 marine3이 생성되고 함수가 끝날 때 소멸되어
static 변수인 total_marine_num이 증가했다가 감소한다
초기화
모든 전역 및 static 변수들은 정의와 동시에 값이 자동으로 0으로 초기화된다
따로 초기화 하지 않아도 되지만 클래스 static변수들은 아래와 같이 초기화한다
int Marine::total_marine_num = 0;
아래처럼은 초기화 시키지 못한다
class Marine {
static int total_marine_num = 0;
}
이게 가능한 꼴은 const static 변수일 때만 가능하다
class Marine {
const static int x = 0;
}
호출 방식
static 변수는 객체 없이도 호출할 수 있어 (객체).(멤버 함수)가 아니라 (클래스)::(static 함수) 형식으로 호출한다
중요!) static 함수 내에서는 클래스의 static 변수만을 이용해야한다
this
Marine& Marine::be_attacked(int damage_earn) {
hp -= damage_earn;
if (hp <= 0) is_dead = true;
return *this;
}
여기서 this는 객체 자신을 가리키는 포인터다
레퍼런스를 리턴하는 함수
// 레퍼런스를 리턴하는 함수
#include <iostream>
class A {
int x;
public:
A(int c) : x(c) {}
int& access_x() { return x; }
int get_x() { return x; }
void show_x() { std::cout << x << std::endl; }
};
int main() {
A a(5);
a.show_x();
int& c = a.access_x();
c = 4;
a.show_x();
int d = a.access_x();
d = 3;
a.show_x();
// 아래는 오류
// int& e = a.get_x();
// e = 2;
// a.show_x();
int f = a.get_x();
f = 1;
a.show_x();
}
int& c = a.access_x();
c = 4;
a.show_x();
여기서 c는 x의 레퍼런스(x의 별명)을 받는다
int &c = x;
이거랑 같은 구조다
int d = a.access_x();
d = 3;
a.show_x();
이건 d가 그냥 int 변수이므로 값 복사가 일어나 d에는 x의 값이 들어간다
(컴파일 에러가 난다)

이런 구조라고 한다
예전에는 이 내용을 이해하지 못했는데 지금 이해가 되는 걸 보니 C# 공부를 나쁘지 않게 한 것 같다
Marine& Marine::be_attacked(int damage_earn) {
this->hp -= damage_earn;
if (this->hp <= 0) this->is_dead = true;
return *this;
}
비슷한 예제로 위의 함수가 있다면
marine2.be_attacked(marine1.attack()).be_attacked(marine1.attack());
이런식으로 동작한다
하지만 Marine&을 Marine으로 바꾸면 값 복사로 동작해서 한번밖에 실행되지 않는다
const 함수
int attack() const;
C++에서는 변수들의 값을 바꾸지 않고 읽기만 하는 상수같은 멤버 함수를 상수 함수로 선언할 수 있다
(기존의 함수의 정의) const;
이런식으로 선언한다고 한다

