chapter3 : 클래스의 기본
C++에서는 구조체(struct)를 이용하여 변수를 선언할때 struct를 붙이 않아도 된다(C에서는 반드시 struct 를 붙여야 했고 이를 피하기 위해 구조체를 선언할때 typedef를 이용하였다). C++에서는 구조체에 함수를 넣을 수 있는데 이는 구조체가 class의 범주에 속하기 때문이다.
클래스 = 맴버변수 + 멤버함수
-데이터 추상화 : 현실세계의 사물을 데이터적인 측면과 기능적 측면을 통해서 정의하는 것.
-클래스 : 추상화된 데이터를 가지고 자료형을 정의 하는 것
-객체 : 클래스를 이용해서 정의된 자료형의 변수
내부접근은 같은 클래스 내의 존재하는 맴버에 의해 접근되는것, 이 이외는 외부 접근이라 한다.
private 으로 맴버가 선언되면 내부접근만 허용되는 것이고 public으로 선언되면 외부접근까지 허용하는 것이다. private도 public도 없으면 private 으로 간주한다 (단 구조체일 경우 default는 public이다).
클래스의 맴버함수가 전달 인자가 없을때 void는 보통 생략한다, 클래스의 내부를 간결하기 위하여 함수는 외부에서 정의가 가능하다(예를 들어 aa 라는 클래스가 있으면 그안에 bb라는 맴버함수가 잇을때 class aa{public: void bb();} 라고만 해놓고 외부에 aa::bb(){}식으로 외부에서 bb를 정의할수 있다). 클래스의 맴버 함수를 내부 선언 한다는 것은 그 함수를 in-line화 하고자 하는 것이다. 맴버 함수를 외부에서 정의 했을 때에 in-line화 하고 싶을 때는 외부 정의시 앞에 inline을 붙여 주면 된다.
chapter4 : 클래스의 완성
캡슐화와 정보은닉을 충족하는 클래스가 좋은 클래스이다.
캡슐화 : 관련 있는 데이터와 함수를 하나의 단위로 묶는 것.
정보은닉 : 객체 외부에서 객체의 맴버 변수에 직접적인 접근을 허용하지 않는것.
정보은닉을 위해 멤버변수의 접근을 위한 맴버함수들을 access method라고 한다.
C++에서는 클래스 선언및 정의 부분에서 맴버 변수를 초기화 할수 없다(java와 c#은 가능).
일반적으로 클래스 객체를 생성과 동시에 초기화 할수 없다(물론 맴버 변수가 public이라면 상관없다). 이럴 때 이용하는 것이 생성자 (constructor)이다.
생성자 : 1.함수이다, 2.클래스의 이름과 같은 이름을 지닌다, 3.리턴하지도 않고 리턴 타입도 선언되지 않는다.
클래스에 생성자가 하나도 정의되어 있지 않을시 default 생성자가 자동 삽입된다. 생성자 역시 함수 이므로 오버로딩이 가능하다. 디폴트 매개 변수 설정 역시 가능하다.
동적메모리가 할당된 클래스는 클래스의 객체의 소멸시 메모리를 반환해야 하는데 이를 자동화하기 위해 이용될 수 있는 것이 destructor(소멸자)이다.
소멸자 : 1.함수이다, 2.클래스의 이름 앞에 ~가 붙은 형태의 이름을 지닌다, 3.리턴하지도 않고 리턴타입도 선언되지 않는다, 4.매개변수를 받을 수 없다.따라서 오버로딩,디폴트 매개 변수 선언이 불가능하다.
소멸자 역시 생성자처럼 아무런 선언이 없을시 디폴트 소멸자가 삽입된다.
생성자 소멸자의 결론 : 클래스를 정의할때에 멤버 변수를 초기화를 위해서 생성자를 항상정의한다. 반면 객체 소멸 시 처리해야할 것(동적 메모리를 해제)이 있을때만 소멸자를 정의한다.
객체를 동적 메모리에 할당해서 생성과 소멸 시에 new와 delete가 사용된다. malloc과 free는 사용될수 없는데 이는 malloc과 free는 단순히 힙 영역에 메모리를 할당할 뿐이지 객체 생성시 필요한 생성자와 소멸시 필요한 소멸자를 호출하는 기능이 없기 때문이다.
this는 자기 참조 포인터로 이름 그대로 자기 자신을 가리키는 용도의 포인터이다.
private으로 선언된 맴버 변수는 원래 외부 접근이 불가능하나 friend로 선언된 전역 함수나 다른 클래스에 의해서 맴버 변수의 외부 접근이 가능해 진다.
chapter5 : 복사생성자
변수 초기화 하는 방법 int val = 20 이렇게 하는 방법이 있고, int val(20)이렇게 하는 방법이 있다. 첫번째 것이 두번째 것으로 묵시적 변환이 일어난 것이다.
복사 생성자 : 자기 자신과 같은 형태의 객체를 인자로 받을 수 있는 생성자 (예, class AA{public: AA(AA& a){}})
복사 생성자를 정의 할때 매개변수에 &(레퍼런스) 기호를 붙여야 한다. 그렇지 않으면 무한 루프에 빠지게 된다(레퍼런스화 되어 있지않다면 무한 반복해서 계속 복사 생성자를 call할 것이다.복사 생성자가 호출되는 시점을 고려해 보면 알수 있다).
복사 생성자 역시 정의 해주지 않아도 디폴트 복사 생성자가 생기나 이럴땐 shallow copy를 하기때문에 객체가 배열이나 스트링처럼 주소를 담고 있는 맴버 변수가 있을때 주소를 카피 하기 때문에 문제가 있을 수 있다. 이럴 땐 직접 복사 생성자를 정의해서 deep copy를 해야 한다.
복사 생성자가 호출되는 시점 : 1.기존에 생성된 객체로 새로운 객체를 초기화하는 경우, 2.함수 호출 시 객체를 값에 의해 전달하는 경우, 3.함수 내에서 객체를 값에 의해 리턴하는 경우.
chapter6 : static 멤버와 const 멤버
const 키워드의 복습 : 1.const double PI=3.14라고 선언시 PI=3.1415라고 하면 error,즉 const라고 지정한 변수는 값을 변화 할수 없다. 2. const int* pN=&n이라고 하고 *pN=20이라고 하면 error, 즉 const화한 포인터 변수는 자신이 가르키는 값을 변화 시킬수 없다(포인터 변수를 통해서 값을 바꿀수 없다). 3.int* const pN=&n1이라고 하면 *pN=20은 가능하나 pN=&n2를 하면 error, 즉 pN이 가리키는 주소가 저장한 value는 변경할수 있으나 pN이 가리키는 주소값 자첼 바꿀수는 없다.
클래스에서 값이 변하지 않는 맴버변수는 const를 지정하면 좋다. 이러한 const화 된 맴버 변수를 초기화 하기 위해서 member initializer라는 기법이 필요하다. 생성자이름(매개변수들) : const 맴버 변수(매개 변수) 꼴로 초기화 한다(예 student라는 class가 있고 그안에 id가 const int화 되어 있으면 id를 초기화 하기위한 생성자는 student(int _id) : id(_id) 가 되어야 한다).
const 함수도 만들수 있다. const화 된 함수는 맴버 변수를 참고 할수는 있으나 조작은 불가능하다. 또한 const화된 함수는 맴버 변수의 포인터를 리턴 할수도 없으며(리턴되는 포인터를 const화 시키면 가능하다, 곧 const char* func() const 라고 리턴되는 타입 char*을 const화 시킨면 가능) const화 되지 않은 함수를 호출할 수도 없다. 이는 다른 경로를 통한 맴버 변수의 조작을 방지하기 위함이다.
const 키워드를 이용해 객체도 상수화가 가능하다. 그렇게 되면 객체의 맴버 변수의 조작이 불가능 할뿐만 아니라 상수화된(const화된) 맴버 함수만 호출이 가능해 진다.
상수함수냐 아니냐에 따라 함수 오버로딩이 가능하다(매개변수가 같더라도 상수화냐 아니냐에 따라 다르게 인식).
클래스의 static 맴버의 특징 : 1.main 함수가 호출되기도 전에 메모리 공간에 올라가서 초기화된다. 따라서 public으로 선언이 된다면, 객체 생성 이전에도 접근이 가능하다(거꾸로 생각하면 static 변수를 private화하면 객체에 의한 접근만 가능해진다). 2.객체의 멤버로 존재하는 것이 아니다. 다만 선언되어 있는 클래스 내에서 직접 접근할 수 있는 권한이 부여된 것이다.
static 맴버변수, static 맴버함수는 다른말로 class 변수, class 함수라고 한다.
explicit 키워드 : 생성자 앞에 explicit를 써주면 묵시적인 생성자 호출을 허용하지 않는다는 의미이다(AA 라는 클래스가 있을때 explicit AA(int _a){}라고 생성자가 explicit 키워드가 붙어있으면 AA a(10)은 가능하나 AA a=10은 불가능)
mutable 키워드 : mutable로 선언된 맴버 변수는 맴버함수가 const라고 선언되었더라도 변경이 가능하다.
const 함수도 만들수 있다. const화 된 함수는 맴버 변수를 참고 할수는 있으나 조작은 불가능하다. 또한 const화된 함수는 맴버 변수의 포인터를 리턴 할수도 없으며(리턴되는 포인터를 const화 시키면 가능하다, 곧 const char* func() const 라고 리턴되는 타입 char*을 const화 시킨면 가능) const화 되지 않은 함수를 호출할 수도 없다. 이는 다른 경로를 통한 맴버 변수의 조작을 방지하기 위함이다.
const 키워드를 이용해 객체도 상수화가 가능하다. 그렇게 되면 객체의 맴버 변수의 조작이 불가능 할뿐만 아니라 상수화된(const화된) 맴버 함수만 호출이 가능해 진다.
상수함수냐 아니냐에 따라 함수 오버로딩이 가능하다(매개변수가 같더라도 상수화냐 아니냐에 따라 다르게 인식).
클래스의 static 맴버의 특징 : 1.main 함수가 호출되기도 전에 메모리 공간에 올라가서 초기화된다. 따라서 public으로 선언이 된다면, 객체 생성 이전에도 접근이 가능하다(거꾸로 생각하면 static 변수를 private화하면 객체에 의한 접근만 가능해진다). 2.객체의 멤버로 존재하는 것이 아니다. 다만 선언되어 있는 클래스 내에서 직접 접근할 수 있는 권한이 부여된 것이다.
static 맴버변수, static 맴버함수는 다른말로 class 변수, class 함수라고 한다.
explicit 키워드 : 생성자 앞에 explicit를 써주면 묵시적인 생성자 호출을 허용하지 않는다는 의미이다(AA 라는 클래스가 있을때 explicit AA(int _a){}라고 생성자가 explicit 키워드가 붙어있으면 AA a(10)은 가능하나 AA a=10은 불가능)
mutable 키워드 : mutable로 선언된 맴버 변수는 맴버함수가 const라고 선언되었더라도 변경이 가능하다.
No comments:
Post a Comment