[ 문제 ]
#include <iostream>
using namespace std;
//`class Rect`를 구현하시오.
//
//- private: `int width, height`
// - 생성자 `(width, height)`
// - `int area() const`
// - `void setWidth(int)`, `void setHeight(int)` : 0 미만이면 0 저장
class Rect {
// 여기에 답안을 작성해주세요.
};
int main() {
Rect r(3, 4);
cout << r.area() << "\n"; // 12
r.setWidth(-5); r.setHeight(2);
cout << r.area() << "\n"; // 0
}[ 개념 ]
- 접근 제어자 :
C++에서
class를 만들고public:이나private:을 아무것도 적지 않으면, 기본적으로 맨 위에 있는 변수들은 자동으로private이 됩니다.class Rect { // 키워드를 안 적어도 자동으로 private 구역이 됨! int width; int height;
public: // 아래에 public 함수들을 나열 Rect(int w, int h); int area() const; };
| 구분 | 접근 범위 | 특징 |
| :-------: | :----------: | :------------------: |
| public | 어디서든 접근 가능 | 외부 공개 API 역할 |
| protected | 클래스 + 자식 클래스 | 상속 관계에서만 접근 가능 |
| private | 클래스 내부만 | 외부/자식 모두 접근 불가 (기본값) |
2. `this` 포인터
핵심 연산자
1. 주소연산자 &
변수 앞에 붙이면 "이 변수의 실제 메모리 주소가 어디야?"라고 묻는 것입니다.
2. 역참조 연산자 *
포인터 변수 앞에 붙이면 "네가 가리키고 있는 주소로 직접 찾아가서 값을 가져와(또는 바꿔)!"라는 의미입니다.
```cpp
int num = 10; // 일반 변수 num에 10 저장
int* ptr = # // ptr이라는 포인터 변수에 num의 '주소'를 저장
cout << ptr << "\n"; // 출력: 0x7ffe... (num의 메모리 주소값)
cout << *ptr << "\n"; // 출력: 10 (ptr이 가리키는 주소로 찾아가서 꺼낸 값)
① 멤버 변수와 매개변수의 이름이 같을 때 (이름 충돌 해결)
class Person {
private:
string name; // 멤버 변수
public:
void setName(string name) { // 매개변수 name
// name = name; (X) -> 매개변수끼리 대입하는 의미 없는 코드가 됨
this->name = name; // (O) -> 진짜 내 멤버 변수에 매개변수 값을 대입!
}
};② 멤버 함수에서 객체 자신을 다시 반환할 때 (연속 호출)
class Counter {
private:
int count = 0;
public:
Counter& add() {
count++;
return *this; // 내 객체 자체를 통째로 반환!
}
};
// 사용 예시: 함수를 기차처럼 이어 붙여 쓸 수 있음
Counter c;
c.add().add().add();③ 비교
| 구문 | 의미 | 실제 역할 |
|---|---|---|
ptr (일반 포인터) | 내가 임의로 지정한 메모리 주소 | 임의의 대상 변수를 원격 제어할 때 사용 |
this (this 포인터) | 나 자신의 메모리 주소 | 함수 내부에서 “지금 이 함수를 호출한 나 자신”을 의미 |
*this | 나 자신의 실제 알맹이(객체) | 함수가 종료되면서 자기 자신을 반환할 때 사용 |
const멤버 함수 멤버 변수 수정 불가능 : 함수 내부에서 멤버 변수의 값을 바꾸려고 하면 컴파일 에러가 발생 다른 일반 함수 호출 불가능 :const함수 안에서는 값을 바꿀지도 모르는 일반 멤버 함수를 호출할 수 없고, 오직 다른const멤버 함수만 호출할 수 있습니다.
#include <iostream>
using namespace std;
class Person {
public:
int age = 20;
// 1. const 함수 (읽기 전용 🔎)
void printAge() const {
// age = 30; // ❌ 에러! const 함수 내에서는 값을 바꿀 수 없습니다.
cout << age << "\n"; // ⭕ 값을 읽어서 출력하는 것만 가능!
}
// 2. 일반 함수 (수정 가능 ✏️)
void birthday() {
age++; // ⭕ 값을 마음대로 바꿀 수 있음!
}
};
int main() {
Person p;
p.printAge(); // 20 출력
p.birthday(); // 나이 1살 증가
p.printAge(); // 21 출력
}[ 풀이 ]
#include <iostream>
using namespace std;
//`class Rect`를 구현하시오.
//
//- private: `int width, height`
// - 생성자 `(width, height)`
// - `int area() const`
// - `void setWidth(int)`, `void setHeight(int)` : 0 미만이면 0 저장
class Rect {
int width;
int height;
public:
Rect(int width, int height)
{
this->width = width;
this->height = height;
}
int area() const
{
return width * height;
}
void setWidth(int width)
{
if (width < 0)
{
this->width = 0;
}
else
{
this->width = width;
}
}
void setHeight(int height)
{
if (height < 0)
{
this->height = 0;
}
else
{
this->height = height;
}
}
};
int main() {
Rect r(3, 4);
cout << r.area() << "\n"; // 12
r.setWidth(-5); r.setHeight(2);
cout << r.area() << "\n"; // 0
}[ 해설 ]
#include <iostream> // 입출력을 위한 헤더 파일 포함
using namespace std; // std:: 네임스페이스 생략 설정
class Rect { // 사각형을 정의하는 Rect 클래스 시작
private: // 외부에서 직접 접근할 수 없는 보호 영역
int width; // 사각형의 가로 길이를 저장하는 멤버 변수
int height; // 사각형의 세로 길이를 저장하는 멤버 변수
public: // 외부(main 함수 등)에서 자유롭게 접근할 수 있는 개방 영역
// 생성자: 객체가 생성될 때 가로, 세로 값을 받아 초기화합니다.
Rect(int width, int height)
{
// 기존의 'this->width;'는 변수를 부르기만 하고 값을 넣지 않는 오류였습니다.
// 대입 연산자(=)를 써서 매개변수 width를 진짜 멤버 변수(this->width)에 채워줍니다.
this->width = width;
this->height = height; // 매개변수 height의 값을 멤버 변수 height에 대입합니다.
}
// 사각형의 넓이를 구해서 반환하는 멤버 함수
// 뒤에 붙은 const는 이 함수 안에서 width나 height 값을 절대 변경하지 않겠다는 의미입니다.
int area() const
{
return width * height; // 가로 * 세로 계산 결과를 반환
}
// 가로 길이를 외부에서 새로 수정하는 함수
void setWidth(int width)
{
// 만약 받아온 가로 길이(매개변수 width)가 0보다 작다면(음수라면)
if (width < 0)
{
this->width = 0; // 사각형의 진짜 멤버 변수 가로 길이를 0으로 강제 세팅합니다.
}
// 그 외의 경우(0 이상인 정상적인 양수라면)
else
{
// 기존의 'width = width;'는 매개변수끼리 값을 주고받는 의미 없는 코드였습니다.
// 명확하게 'this->'를 붙여서 진짜 멤버 변수에 매개변수 값을 대입해 줍니다.
this->width = width;
}
}
// 세로 길이를 외부에서 새로 수정하는 함수
void setHeight(int height)
{
// 입력받은 세로 길이가 음수인지 검사합니다.
if (height < 0)
{
this->height = 0; // 음수 유입 시 데이터 왜곡을 막기 위해 0으로 안전하게 저장합니다.
}
// 입력받은 세로 길이가 정상적인 양수라면
else
{
this->height = height; // 전달받은 값을 진짜 멤버 변수 height에 대입합니다.
}
}
}; // 클래스 정의 종료 (세미콜론 필수)
int main() { // 프로그램의 시작점인 main 함수
Rect r(3, 4); // 가로 3, 세로 4를 가지는 사각형 객체 r 생성 (생성자 호출됨)
cout << r.area() << "\n"; // area() 함수가 3 * 4를 계산하여 12 출력
r.setWidth(-5); // 음수인 -5를 전달 -> setWidth 내부 조건문에 의해 가로(width)는 0이 됨
r.setHeight(2); // 양수인 2를 전달 -> 세로(height)는 정상적으로 2가 됨
cout << r.area() << "\n"; // 가로가 0이 되었으므로 0 * 2를 계산하여 0 출력
}