접근제어 지시자
- public : 모든 접근 허용
- protected : 상속관계 시, 유도 클래스에서 접근허용
- private : 클래스 내에서만 접근 허용
정보 은닉
- 멤버변수를 private로 선언하고
- 해당 변수에 접근하는 함수를 별도 정의
- 안전한 형태로 변수의 접근 유도
캡슐화
- 캡슐화의 범위를 결정하는 일이 쉽진 않음
- 구현하는 프로그램의 성격과 특성에 따라서 적용하는 범위가 달라진다.
생성자
- 객체 생성과 동시에 초기화 가능(이걸 배우기 전엔 init 함수를 클래스 내에 따로 정의 했음 - 불편함)
- 클래스의 이름과 함수의 이름이 동일
- 반환형 X, 실제로 반환 X
- 객체 생성시 딱 한번 호출
- 인자 정보 전달 가능
- 오버로딩 가능
- 디폴트 매개변수 값 설정 가능
- 생성자는 이니셜라이저처럼 선택적으로 존재하는 대상이 아님 → 생성자는 반드시 호출됨
- 우리가 생성자를 정의하지 않으면, '디폴트 생성자'가 자동으로 삽입되어 호출 됨
소멸자
- 객체소멸시 반드시 호출되는 것은 소멸자.
- 클래스의 이름 앞에 '~'가 붙은 형태
- 반환형 X, 실제로 반환 X
- 매개변수는 void형으로 선언, 오버로딩 및 디폴트 값 설정 불가.
- 소멸자는 객체소멸 과정에서 자동으로 호출.
- 프로그래머가 직접 소멸자를 정의하지 않으면, 디폴트 생성자와 마찬가지로 아무런 일도 하지 않는 디폴트 소멸자가 자동으로 삽입.
- 대게 생성자에서 할당한 리소스의 소멸에 사용.
- 생성자 내에서 new 연산자를 이용해서 할당해 놓은 메모리 공간이 있으면, 소멸자에서 delete 이용, 메모리 소멸
이니셜라이저
- 이니셜라이저를 이용하면 선언과 동시에 초기화가 이뤄지는 형태로 바이너리 코드가 생성
- 반면, 생성자의 몸체부분에서 대입연산을 통한 초기화를 진행하면, 선언과 초기화를 각각 별도의 문장에서 진행하는 형태로 바이너리 코드가 생성
- const 멤버변수도 이니셜라이저를 이용하면 초기화 가능
- 참조자도 선언가능(원래는 const 변수와 마찬가지로 선언과 동시에 초기화가 이뤄져야 함)
객체
- 데이터(변수로 표현)와 기능(함수로 표현)으로 구성
- 객체가 되기 위해서는 반드시 하나의 생성자가 호출되어야 한다.
- 생성자를 정의하지 않은 클래스에는 컴파일러에 의해 디폴트 생성자가 자동으로 삽입
- 단, C언어의 malloc함수를 대신 이용하면 생성자는 호출되지 않는다.
- 힙에 할당된 메모리 공간은 변수로 간주하여, 참조자를 통한 참조가 가능하다
객체배열
- 객체 기반의 배열은 Bread arr[10]; 이런 형태나 동적으로 Bread * ptrArr = new Bread[10];
- 위 숫자 만큼의 객체가 모여 배열 구성
- 배열의 선언과정에서는 호출할 생성자를 별도로 명시하지 못함
- 일일이 초기화 과정을 거쳐야 함
객체 포인터 배열
- 객체의 주소 값 저장이 가능한 포인터 변수로 이뤄진 배열
this 포인터
- 객체 자신을 가리키는 용도로 사용되는 포인터
- 그 주소 값과 자료형이 정해져있지 않은 포인터
- this 포인터를 이용해 생성자의 매개변수를 멤버변수로 대입할 수 있다.
참조의 정보(참조 값)
- 참조자를 사용하면 선택된 변수를 참조할 수 있는 참조의 정보가 전달된다.
- 즉, 변수 X를 참조할 수 있는 참조 값이 참조자 ref에 전달되어, ref가 변수 num을 참조하게 된다.
얕은 복사
- 디폴트 복사 생성자는 '얕은 복사 진행'
- 얕은 복사시 소멸자는 한 번만 호출된다.
- 왜?
- 문자열을 얕은 복사한다면, 복사한 객체가 원래의 객체와 같은 문자열 메모리 주소를 참조하기 때문
- 즉, 하나의 문자열을 두 개의 객체가 동시에 참조하는 현상
- 만약 복사된 객체의 소멸자가 호출되면, 본 객체가 참조하는 공간이 이미 삭제되었기 때문에, 본 객체에서 소멸자를 사용하는데 문자가 된다.
깊은 복사
- 위 얕은 복사의 문제를 해결하기 위해 나온 것이 '깊은 복사'
- 멤버뿐만 아니라, 포인터로 참조하는 대상까지 깊게 복사한다는 뜻.
- 멤버변수들을 멤버 대 멤버로 복사
임시객체
- 임시로 생성되었다가 소멸되는 객체
- 임시객체는 다음 행으로 넘어가면 바로 소멸되어 버린다.
- 참조자에 참조되는 임시객체는 바로 소멸되지 않는다.
const 객체와 const 객체의 특성들
- 객체에 const 선언이 붙게 되면, 이 객체를 대상으로는 const 멤버함수만 호출이 가능하다.
- 멤버변수에 저장된 값을 수정하지 않는 함수는 가급적 const로 선언해서, const 객체에서도 호출이 가능할 필요
- const 선언유무도 함수 오버로딩의 조건에 해당.
클래스의 friend 선언
- A 클래스가 B 클래스를 대상으로 friend 선언을 하면, B 클래스는 A 클래스의 private 멤버에 직접 접근 가능
- 단, A 클래스도 B 클래스의 private 멤버에 직접 접근이 가능하려면, B 클래스가 A 클래스를 대상으로 friend 선언을 해줘야 한다.
- friend 선언은 private 멤버의 접근을 허용하는 선언.
- friend 선언은 객체지향의 '정보은닉'을 무너뜨리는 문법
- 지나치게 사용하면 위험, 필요한 상황에서 소극적으로 사용
- 함수 맨 앞에 friend 선언을 함으로써 접근 가능
Static
- 전역변수에 선언된 static의 의미 : 선언된 파일 내에서만 참조를 허용
- 함수 내에 선언된 static의 의미 : 한번만 초기화되고. 지역변수와 달리 함수를 빠져나가도 소멸되지 않음.
Static 멤버변수(클래스 변수)
- 클래스당 하나씩만 생성됨
- 객체가 생성될 때마다 함께 생성되어 객체별로 유지되는 변수가 아님
- 객체를 생성하건 않건, 메모리 공간에 딱 하나만 할당이 되어서 공유되는 변수
- 어디서든 접근이 가능하다. private으로 선언되면, 해당 클래스만, public으로 선언되면 어디서든 접근 가능.
Static 멤버함수
- 선언된 클래스의 모든 객체가 공유한다.
- public으로 선언되면, 클래스의 이름을 이용해서 호출이 가능하다.
- 객체의 멤버로 존재하는 것이 아니다.
- static 멤버함수 내에서는 static 멤버변수와 static 멤버함수만 호출이 가능하다.
const static 멤버
- const 멤버변수(상수)의 초기화는 이니셜라이져(:)를 통해야만 했다.
- const static 멤버변수(상수)는 선언과 동시에 초기화가 가능하다.
- 클래스가 정의될 때 지정된 값이 유지되는 상수이기 때문에, 초기화가 가능하도록 정의
mutuable
- 가급적 사용의 빈도수를 낮춰야 함
- const 함수 내에서의 값의 변경을 예외적으로 허용한다.
- 매우 예외적인 경우에 한해서 사용하는 키워드
상속
- 좋은 프로그램은 프로그램 변경의 요구에 대처가 가능해야 한다.
- 상속은 프로그램 변경을 최소로 하면서도 변화에 잘 대처할 수 있다.
- 상속 : 자신이 지니고 있는 고유의 특성 이외에 다른 것으로부터 특성을 받음
- ex. soboru 클래스가 bread 클래스를 상속하게 되면, soboru는 bread가 지니고 있는 모든 멤버를 물려받음
- 즉, 상속을 하게되면, 상속의 대상이 되는 클래스의 멤버까지도 객체 내에 포함이 된다.
- 상속받은 클래스 생성자는 상속한 클래스 멤버에 대해서도 초기화를 해야 한다.
- soboru 클래스 생성자는, bread 클래스의 생성자를 호출해서 bread 클래스의 멤버를 초기화하는 것이 좋음
- 이니셜라이저를 이용해서 상속하는 클래스의 생성자 호출
- 접근제한 기준이 클래스이면, soboru 멤버함수 내에서는 bread 멤버함수에 직접 접근이 불가능하다.
- 그러나 private 멤버도 상속이 이뤄졌고, 초기화도 가능했다. 다만 직접 접근이 불가능 해 public으로 간접 접근
- 상위 - 하위 / 기초 - 유도 / 슈퍼 - 서브 / 부모 - 자식 으로 '상속을 한' 과 '상속을 받은' 을 표현
- 유도 클래스의 객체 생성과정에서 기초 클래스의 생성자는 100% 호출된다.
- 유도 클래스의 생성자에서 기초 클래스의 생성자 호출을 명시하지 않으면, 기초 클래스의 void 생성자가 호출된다.
- 유도 클래스의 객체가 소멸될 때에는, 유도 클래스의 소멸자가 실행되고 난 다음에 기초 클래스의 소멸자가 실행
- 스택에 생성된 객체의 소멸순서는 생성순서와 반대이다.
- 생성자에서 동적 할당한 메모리 공간은 소멸자에서 해제한다.
- 상속의 이유 : 상속을 통해 연관된 일련의 클래스에 대해 공통적인 규약을 정의할 수 있음.
- 기초 클래스에서 상속 받은 객체는 모두 기초 클래스 객체로 바라볼 수 있다.
protected
- 접근 범위 private < protected < public
- protected로 선언된 멤버변수는 이를 상속하는 유도 클래스에서 접근 가능
- 기본적으로 기초 클래스와 이를 상속하는 유도 클래스 사이에서도 '정보은닉'은 지켜지는 게 좋음.
상속형태
- public 상속, private 상속, protected 상속 가능
- 해당 상속이 선언되면, 그 상속 형태보다 넓은 범위는 해당 상속 형태로 변경시켜서 상속
- ex) protected 상속 시 public이 protected로 바뀜.
- 평균적으로 대부분 public 상속
객체 포인터의 참조 관계
- 포인터 변수는 유도 클래스의 객체도 가리킬 수 있다.
- C++에서, X 포인터 변수는 X 객체 또는 X를 직접 혹은 간접적으로 상속하는 모든 객체를 가리킬 수 있다.
함수의 오버라이딩(오버로딩 X)
- 유도 클래스가 기초 클래스와 동일한 이름의 함수가 있으면, 함수는 오버라이딩 된다.
- 즉, 유도 클래스 내에서 기초 클래스와 같은 이름 함수가 호출되면, 유도 클래스의 함수가 호출된다.
- 매개변수의 자료형 및 개수가 다르면, 오버로딩이 된다.
- 즉, 오버라이딩은 기초 클래스의 함수를 유도 클래스에서 새롭게 정의해서 사용한다고 생각하면 됨.
포인터
- C++ 컴파일러는 포인터 연산의 가능성 여부를 판단할 떄, 포인터의 자료형을 기준으로 판단하지, 실제 가리키는 객체의 자료형을 기준으로 판단하지 않는다.
- 객체 포인터, 포인터 형에 해당하는 클래스에 정의된 멤버에만 접근이 가능.
가상함수
- 함수가 가상함수로 선언되면, 해당 함수호출 시, 포인터의 자료형을 기반으로 호출대상을 결정하지 않고,
- 포인터 변수가 실제로 가리키는 객체를 참조하여 호출의 대상을 결정한다.
연산자 오버로딩
- 함수의 오버로딩처럼 연산자의 오버로딩을 통해서, 기존 존재하던 연산자의 기본 기능 이외에 다른 기능 추가 가능.
- C++에서 제시하는 하나의 약속에 지나지 않음.
- 객체도 기본 자료형 변수처럼 덧셈, 뺄셈, 혹은 곱셈과 같은 연산들을 가능하게 하려고 함
- 'operator' 키워드와 '연산자'를 묶어서 함수의 이름을 정의하면, 함수의 이름을 이용한 함수의 호출 + 연산자를 이용한 함수의 호출 허용
- 객체를 피연산자로 사용한 연산자의 이름 앞에 operator라는 이름을 붙여서 완성되는 이름의 함수를 호출
- 즉, pos1 + pos2; = pos1.operator+(pos2); 와 같다.
- pos1 + pos2가 pos1.operator+(pos2)로 해석되어서 컴파일 되기 때문.
- 1) 멤버함수에 의한 연산자 오버로딩 : (+ 연산자를 멤버함수를 이용해서 오버로딩) => pos1.operator+(pos2)
- 2) 전역함수에 의한 연산자 오버로딩 : (+ 연산자를 전역함수를 이용해서 오버로딩) => operator+(pos1, pos2)
- 멤버함수 기반으로 오버로딩 된 함수가 전역함수 기반으로 오버로딩 된 함수보다 우선시되어 호출된다.
- 주요사항
- 1) 본래의 의도를 벗어난 형태의 연산자 오버로딩 X -> 잘못 사용하면 프로그램을 복잡하고, 이해하기 어렵게 만듦
- 2) 연산자의 우선순위와 결합성은 바뀌지 않는다.
- 3) 매개변수의 디폴트 값 설정이 불가능 하다.
- 4) 연산자의 순수 기능까지 빼앗을 수 없다.
- 연산자가 오버로딩되면, 피연산자의 종류에 따라서 연산의 방식이 달라진다. => 그래서 연산자 오버로딩
- ++pos;
- 1) pos.operator++(); - 멤버함수로 오버로딩이 된 경우
- 2) operator++(pos); - 전역함수로 오버로딩 된 경우
템플릿에 대한 이해
- 템플릿에는 '모형자'라는 뜻이 담겨 있음
- 모형자 : 모형을 만들어낸다. 모형의 틀은 결정되어 있지만, 모형의 색은 결정되어 있지 않아서 결정해야 한다.
- 함수 템플릿은 함수를 만들어 낸다. 함수의 기능은 결정되어 있지만, 자료형은 결정되어 있지 않아서 결정해야 한다.
- 함수 템플릿도 다양한 자료형의 함수를 만들어 낼 수 있다.
- 함수 템플릿 : 함수를 만드는데 사용되는 템플릿
- 템플릿 함수 : 템플릿을 기반으로 만들어진 함수
'Language&Framework&Etc > C++' 카테고리의 다른 글
C++ 상속 예제 (0) | 2021.01.10 |
---|---|
클래스의 완성(04-4) 클래스와 배열 그리고 this 포인터 (0) | 2021.01.10 |
구조체 및 클래스 간단히 정리(C와 C++) (0) | 2021.01.09 |
클래스의 완성(04-3) 생성자(Constructor)와 소멸자(Destructor)-2 (0) | 2020.12.28 |
클래스의 완성(04-3) 생성자(Constructor)와 소멸자(Destructor)-1 (0) | 2020.12.25 |