숏컷 코드
class Counter {
public:
Counter() : count_{0} { } // 기본 생성자
void increment() { ++count_; }
void reset() { count_ = 0; }
int value() const { return count_; } // const 멤버 함수
private:
int count_; // 외부에서 직접 접근 불가
};
Counter c;
c.increment();
std::cout << c.value(); // 1데이터만 묶을지, 유효한 상태를 지키는 객체를 만들지부터 나누면 읽기 쉽습니다. struct는 공개 데이터 묶음에, class는 불변식을 지키는 쪽에 더 자주 갑니다.
문법
클래스 카드에서 먼저 다시 보는 기본형은 아래입니다.
- 멤버 데이터와 멤버 함수
public/private- 생성자
const멤버 함수
struct Point {
int x;
int y;
};
class Counter {
public:
void increment() { ++count_; }
int value() const { return count_; }
private:
int count_{0};
};struct와 class의 차이는 기본 접근 제어다
C++에서 struct와 class의 유일한 차이는 기본 접근 제어입니다. struct는 기본이 public, class는 기본이 private. 관례상 데이터 중심 단순 집합은 struct, 불변식(invariant)을 보호하는 캡슐화가 있으면 class를 씁니다.
struct Point { int x; int y; }; // 데이터 집합 — struct
class Engine { ... }; // 불변식 보호 — class
Point p{3, 4}; // 직접 접근 자연스러움
// Engine e; e.rpm = -100; // ❌ private으로 막힘멤버 변수를 private으로 두고 멤버 함수를 통해서만 접근하면 객체가 항상 유효한 상태를 유지하도록 강제할 수 있습니다.
class Temperature {
public:
void set(double celsius) {
if (celsius < -273.15) throw std::invalid_argument{"절대영도 이하"};
value_ = celsius;
}
double get() const { return value_; }
private:
double value_ = 20.0; // 외부가 -1000으로 설정하는 것을 막음
};const가 붙은 멤버 함수는 객체의 상태를 변경하지 않겠다는 약속입니다. const 객체나 const 참조를 통해서는 const 멤버 함수만 호출할 수 있습니다.
class Circle {
public:
double area() const { return 3.14159 * r_ * r_; } // 읽기 전용
void resize(double r) { r_ = r; } // 상태 변경
private:
double r_;
};
void print(const Circle& c) {
std::cout << c.area(); // ✅ const 함수 — OK
// c.resize(5); // ❌ const 객체에서 비const 함수 호출 불가
}선택 기준
- 공개 데이터 묶음이면
struct - 상태를 보호해야 하면
class+private - 읽기 전용 동작이면
const멤버 함수 - 생성 시점에 상태를 고정해야 하면 생성자와 멤버 초기화
- 외부가 직접 만지면 깨질 값이면 setter나 생성자로만 받는다
주의할 점
생성자를 직접 정의하면 컴파일러 기본 생성자가 자동 생성되지 않습니다.
class Widget {
public:
Widget(int id) : id_{id} { } // 사용자 정의 생성자
private:
int id_;
};
Widget w; // ❌ 컴파일 오류 — 기본 생성자 없음
Widget w2{5}; // ✅
// ✅ 기본 생성자를 명시적으로 추가
class Widget2 {
public:
Widget2() = default; // 기본 생성자 명시적 생성
Widget2(int id) : id_{id} { }
private:
int id_ = 0;
};// ❌ public 데이터만 두면 음수처럼 금지해야 할 값도 바로 들어간다
struct TemperatureBad {
double value;
};
// ✅ class로 감싸면 유효성 검사를 생성자나 setter에 둘 수 있다
class TemperatureGood {
public:
explicit TemperatureGood(double value) {
if (value < -273.15) throw std::invalid_argument{"too low"};
value_ = value;
}
private:
double value_;
};참고 링크
1 sources