10) 클래스(1)
파이썬의 클래스와 크게 다르지는 않습니다.
10.1 클래스와 인스턴스
- 클래스 : 인스턴스를 찍어내는 틀
- 멤버 함수는 모든 인스턴스가 공유함.
- 인스턴스 : 해당 클래스 타입의 객체
- 멤버 변수는 각 인스턴스마다 고유함.
10.2 클래스의 선언
class Book{
private: // 접근제한자, 바로 밑에서 설명할 예정
int current_page;
void Move(int page);
void Move(int page){
current_page = page;
// 파이썬은 self.current_page라고 했는데 그러지 않아도 됩니다.
}
}
- 한 클래스에서 여러 접근제한자를 설정할 수 있음
- 클래스 선언 안팎에서 멤버함수의 정의가 가능함.
클래스 선언 밖에서 멤버함수를 정의하기 위해서는 ::를 통해서 namespace를 제한해야합니다.
void Book::Move(int page){
current_page = page;
}
10.3 접근제한자
파이썬에서는, 특정 인스턴스가 멤버변수에 접근하는 것을 제한하지 않습니다.
물론 __foo
와 같은 방식으로 객체.__foo
형식의 접근을 막는 방법은 존재하지만, 기본적으로 다른 개념(맹글링)을 위해서 사용되는 것이지, private의 개념은 파이썬에서 존재하지 않는다고 합니다.
C++에서는 클래스의 접근제한자를 통해서 인스턴스에서 멤버변수(함수)로의 접근여부를 결정할 수 있습니다.
-
public (구조체, 공용체의 기본값)
- 객체의 public 변수에는 항상 접근 가능함.
-
private (클래스의 기본값)
- 객체의 private 변수에는 직접적으로 접근이 불가능함!
class Book { private: int id; }; int main(){ Book my_book; my_book.id = 23454654; }
prog.cc: In function 'int main()': prog.cc:10:13: error: 'int Book::id' is private within this context 10 | my_book.id = 23454654; | ^~ prog.cc:6:6: note: declared private here 6 | int id; | ^~
- 그렇지만, public함수를 통해서 간접적으로 호출은 가능함.
class Book { private: int id; public: void set_id(int new_id); }; void Book::set_id(int new_id){ id = new_id; std::cout << id; // 23454654 } int main(){ Book my_book = Book(); my_book.set_id(23454654); }
-
- protected
-
이 부분은 파생클래스와 friend에 대해서 배워야 이해할 수 있을 것 같아서 나중에 적겠습니다.
10.4 this 포인터
this 포인터는 파이썬의 self와 비슷한 개념입니다.
다만 포인터이기 때문에 객체 자기자신의 주소를 가리킨다는 차이점이 있습니다.
void Book::set_id(int new_id){
id = new_id;
std::cout << id; // 23454654
}
방금 이런 식으로 객체의 id라는 멤버변수에 접근할 수 있었는데, 사실 이런 식으로 해도 똑같습니다.
void Book::set_id(int new_id){
(*this).id = new_id;
std::cout << id; // 23454654
}
왜냐하면 *
(포인터 변수 역연산자)를 통해서 (*this)
는 객체 자기자신을 뜻하기 때문입니다.
그리고, (*this).id
의 *
와 .
역할을 한꺼번에 할 수 있는 ->연산자도 있습니다.
void Book::set_id(int new_id){
this->id = new_id;
std::cout << id; // 23454654
}
->
연산자는 보통 new
연산자를 통해 동적으로 할당된 객체에 접근하기 위해서 자주 쓰인다고 합니다.
10.5 this 포인터에 대한 추가적인 정보들
- this 포인터를 사용하는 이유 : 객체 자기자신을 반환해야할 일이 있기 때문
const Book& Book::whichIsBetter(Book &another_book){
return (this->id) > (another_book.id) ? (*this) : another_book
} // 아이디가 더 큰 책 객체를 반환하는 함수.
int main(){
Book my_book;
Book your_book;
my_book.set_id(12345);
your_book.set_id(2345);
std::cout << &my_book; // 0x7ffd0891842c
std::cout << &(my_book.whichIsBetter(another_book)); // 0x7ffd0891842c
}
이 때, 반환타입을 Book&
으로 지정하는 이유는 객체 그자체를 복사하지 않고 반환하기 위함입니다.
- this 포인터는 언제나 포인터 상수
- static 멤버 함수는 this 포인터를 가지지 않는다 : 파이썬의 static 함수와 비슷한 느낌.