이 코드는 객체지향 프로그래밍에서 const
키워드의 사용과 의미를 설명하는 예제입니다. const
가 멤버 변수, 멤버 함수, 그리고 포인터에 어떤 영향을 미치는지 보여주기 위해 작성되었습니다. 이제 코드의 각 부분을 주석을 기반으로 분석해보겠습니다.
#include <iostream>
using namespace std;
class Person
{
private:
const string _name = "david"; // const 멤버 변수는 인라인으로 초기화 가능
float _weight;
float _height;
public:
Person(const string& name, float weight, float height)
: _name(name), _weight(weight), _height(height) // const 멤버 변수는 멤버 초기화 리스트에서 초기화 가능
{
}
float getWeight(/* const Person* this */) const
{
// const가 붙은 멤버 함수에서의 this 포인터의 타입
// const Person*
return _weight;
}
float getHeight(/* Person* this */)
{
// this 포인터의 타입
// Person*
return _height;
}
};
int main()
{
const Person person("David", 75.f, 181.f);
cout << person.getWeight() << endl; // getWeight에 const Person*가 넘어간다.
//cout << person.getHeight() << endl; // getHeight에 const Person*을 넘길 수 없다.
Person *person0 = new Person("Daniel", 57.f, 175.f);
const Person* person1 = person0; // 변환 가능
//Person* person2 = person1; // 변환 불가능
}
private
멤버 변수 선언:
const string _name = "david"; // const 멤버 변수는 인라인으로 초기화 가능
_name
변수는 const
로 선언되어, 한 번 초기화되면 변경할 수 없습니다. 여기서 _name
은 "david"로 인라인 초기화되었습니다. C++11부터는 이런 방식으로 const
멤버 변수를 인라인으로 초기화하는 것이 가능합니다._weight
와 _height
는 const
가 붙지 않았으므로 나중에 값이 변경될 수 있습니다.생성자:
Person(const string& name, float weight, float height)
: _name(name), _weight(weight), _height(height) // const 멤버 변수는 멤버 초기화 리스트에서 초기화 가능
{
}
_name
, _weight
, _height
를 초기화합니다. _name
은 const
이므로 반드시 초기화 리스트에서 초기화해야 합니다. 생성자 본체에서 _name
을 초기화하려고 하면 컴파일 오류가 발생합니다.const
멤버 변수는 생성될 때 초기화되어야 하며, 그 후 변경이 불가능합니다.getWeight
멤버 함수:
float getWeight(/* const Person* this */) const
const
가 붙은 멤버 함수입니다. 이 함수는 객체의 멤버 변수를 변경하지 않겠다는 것을 보장합니다.const
멤버 함수에서 this
포인터는 const Person*
타입입니다. 즉, 이 함수 내부에서 멤버 변수를 수정할 수 없습니다._weight
값을 반환합니다.getHeight
멤버 함수:
float getHeight(/* Person* this */)
const
가 붙지 않은 멤버 함수입니다. 이 함수는 멤버 변수를 수정할 수 있습니다.this
포인터는 Person*
타입이므로, 이 함수는 객체의 멤버 변수를 수정할 수 있습니다._height
값을 반환합니다.main
함수 분석const Person
객체 생성:
const Person person("David", 75.f, 181.f);
person
객체는 const
로 선언되었습니다. 이는 person
객체의 멤버 변수를 변경할 수 없음을 의미합니다.const
객체에서는 const
로 선언된 멤버 함수만 호출할 수 있습니다.getWeight
호출:
cout << person.getWeight() << endl; // getWeight에 const Person*가 넘어간다.
person
객체가 const
이므로, getWeight
함수는 호출이 가능합니다. 이는 getWeight
가 const
멤버 함수이기 때문입니다.getWeight
는 const Person*
타입의 this
포인터를 사용하므로, person
객체의 상태를 변경하지 않습니다.getHeight
호출 시도:
// cout << person.getHeight() << endl; // getHeight에 const Person*을 넘길 수 없다.
person
객체가 const
로 선언되었기 때문입니다. getHeight
함수는 const
멤버 함수가 아니므로 const
객체에서 호출할 수 없습니다.포인터 변환:
Person *person0 = new Person("Daniel", 57.f, 175.f);
const Person* person1 = person0; // 변환 가능
//Person* person2 = person1; // 변환 불가능
person0
은 Person*
타입의 포인터입니다. 이는 동적으로 할당된 Person
객체를 가리킵니다.person1
은 const Person*
타입의 포인터입니다. Person*
타입의 포인터를 const Person*
타입으로 변환하는 것은 가능합니다. 이는 person1
이 가리키는 객체를 수정하지 않겠다는 의미입니다.const Person*
를 다시 Person*
로 변환하려고 하면 오류가 발생합니다. 이는 const
타입을 변환하여 const
속성을 무시하려는 시도이기 때문에 허용되지 않습니다.const
멤버 변수는 초기화 이후 변경할 수 없으며, 생성자 초기화 리스트에서만 초기화할 수 있습니다.const
멤버 함수는 객체의 상태를 변경하지 않음을 보장하며, const
객체에서만 호출할 수 있습니다.const
포인터는 가리키는 객체의 내용을 변경할 수 없음을 나타냅니다. const Person*
는 Person*
에서 변환이 가능하지만, 반대로 변환할 수는 없습니다.