www.freelec.co.kr / 25,000원 / 1쇄 2004.04.01
-------------------------------------------------------------------------------------------------
## C기반의 C++ 1
-------------------------------------------------------------------------------------------------
21 : #include<iostream> ... 새로운 버젼의 헤더파일을 구버젼과 구별
30 : 함수 오버로딩 ... 매개변수의 타잎 및 개수가 다르면 문제되지 않으며,
34 : 디폴트 매개 변수 ... int function(int a = 0)
39 : in-line 함수 ... inline int SQUARE(int x) { return x*x; }
[참고;요즘 컴파일러는 퇴적화를 수행하므로 in-line 키워드 있건 없건 큰 의미 없음]
42 : namespace A_COM
{
void function(void) ...
}
46 : using A_COM::function
-------------------------------------------------------------------------------------------------
## C기반의 C++ 2
-------------------------------------------------------------------------------------------------
65 : bool 형은 true, false를 갖는다
66 : reference = 별명 = '&'
int val = 10;
int *pVal = &val; //주소값을 얻기 위해 사용
int &rVal = val; //레퍼런스 선언을 위해 사용
70 : int &ref1; //초기화되지 않았으므로 에러
int &ref2 = 10; //상수가 올 수 없으므로 에러
71 : 포인터 call-by-reference ... 포인터가 가리키는 메모리 공간에 직접 접근 가능 / 포인터 연산 가능성 내포 (에러!)
void swap(int *a, int *b)
73 : 레퍼런스 call-by-reference ... 외부 존재 변수 직접 접근 가능 + 포인터 연산 방지
void swap(int &a, int &b)
77 : 레퍼런스를 이용한 성능향상 ... 매개변수 전달기 큰 크기의 복사가 불필요
85 : new, delete
int *val = new int;
int *arr = new int[size];
...
delete val;
delete []arr;
88 : #define DEBUG 1 //테스트 버젼 컴파일 시
//#define DEBUG 0 //최종버젼 컴파일 시
#if DEBUG ==1
if (arr == NULL){
cout<<"메모리 할당 실패!"<<endl;
return -1;
}
#endif
-------------------------------------------------------------------------------------------------
## 클래스의 기본
-------------------------------------------------------------------------------------------------
101 : 객체지향 도입
클래스 = Attribute(특성) + Method(방법)
클래스 = 멤버변수 + 멤버함수
105 : 클래스를 정의 한다는 것은 자료형을 하나 정의하는 것이다.
클래스를 이용해 정의된 자료형의 변수는 객체(Object)
클래스를 기반으로 객체를 생성하는 것을 인스턴스화(Instantiation) 이라고 한다.
-------------------------------------------------------------------------------------------------
## 클래스의 완성
-------------------------------------------------------------------------------------------------
127 : 정보은닉 ... private를 써서 변수 직접 접근을 막는다 / 경계 검사 삽입이 가능함
128 : 캡슐화 ... 관련 있는 데이터와 함수를 하나의 단위로 묶기 (ShowData();)
134 : 오늘날의 객체지향에 있어서 캡슐화는 상속보다도 중요한 개념으로 여겨지고 있다
141 : 생성자/소멸자
158 : 객체 배열 생성 ... 생성자/소멸자가 배열 개수 만큼 호출됨
Point arr[5];
160 : 객체 포인터 배열 ... stack에 4byte 크기로 포인터 배열(실 객체의 주소값 할당)이 생성되고 객체는 heap 에 생성됨
Point *arr[5];
162 : new/malloc 차이점 ... C++ 에서 말하는 객체 생성 조건을 만족하려면 메모리 할당시 생성자를 호출해야 함!
167 : friend 선언 ... 클래스 내부에서 friend로 선언에 외부 함수에 대해서는 private로 선언된 클래스 내부 변수 접근 허용
class Counter {
...
friend void SetX(Counter &c, int val);
}
void SetX(Counter& c, int val){
c.val = val;
}
-------------------------------------------------------------------------------------------------
## 복사생성자
-------------------------------------------------------------------------------------------------
186 : 복사생성자 ... 자신과 같은 형태의 객체를 인자로 받을 수 있는 생성자
class AAA {
AAA(const AAA& a){
this->val = a.val;
}
}
189 : 디폴트 복사 생성자 ... 프로그래머가 굳이 작성하지 않아도 변수對변수를 복사하는 디폴트 복사 생성자가 만들어 짐
194 : 얕은 복사 (shallow copy) ... 디폴트 복사의 문제점 ~ reference로 객체를 복사하므로 복사된 객체의 소멸자 호출시
본 객체의 메모리가 해제되므로 본 객체의 소멸자 호출시 에러 발생
195 : 깊은 복사 (deep copy) ... 복사 생성자를 직접 정의해서 본 객체의 변수 복사시 메모리를 할당해서 값을 복사함
Person::Person(const Person& p)
{
name = new char[strlen(p.name)+1]; //본 객체의 변수 크기만큼 메모리 할당 후
strcpy(name, p.name); //값을 복사
}
198 : 복사생성자호출시점 1/3 ... 기존 객체로 새로운 객체를 초기화 할 때
AAA obj1;
AAA obj2 = obj1;
199 : 복사생성자호출시점 2/3 ... 함수 호출 시 객체를 값에 의해 전달할 경우
void function(AAA a) { a.ShowData(); }
int main(){
AAA obj(30);
function(obj); // 이순간 function에 obj 값을 전달하기 위해 복사생성자가 호출되어 함수내에 로컬 객체가 만들어짐
202 : 복사생성자호출시점 3/3 ... 함수 내에서 객체를 값에 의해 리턴하는 경우
AAA function(void) {
AAA a(10);
return a;
}
void main() {
function(); //이 함수 내에서 생성된 객체를 return시 main에 전달하기 위해 복사생성자가 호출됨
-------------------------------------------------------------------------------------------------
## static 멤버와 const 멤버
-------------------------------------------------------------------------------------------------
213 : const 키워드 복습
1) 변수값을 상수화
const double PI = 3.14;
PI = 3.1415; //에러
2) 포인터가 가리키는 데이터 상수화
int n=10;
const int* pN = &n;
*pN = 20; //에러
3) 포인터 자체를 상수화
int n1 = 10;
int n2 = 20;
int* const pN = &n1;
*pN = 20; //값은 바꿀 수 있다
pn = &n2; //에러
* const를 이용해 프로그램 오류를 방지함. 프로그램을 안정적으로 작성하는데 기여
215 : 멤버 이니셜라이저(member initializer) ... const 선언된 멤버변수의 초기화 방법
class Student {
const int id;
int age;
Student (int _id, int _age, ...):id(_id),age(_age)
{ ...
217 : const 멤버 함수 ... 함수를 통해서 변수를 바꿀 수 없다
void ShowData() const {
cout << "이름 : " << name << endl //멤버변수의 값을 바꾸는 짓을 할 수 없다!
219 : 상수화 된 함수에서 상수화 되지 않은 함수를 호출하면 컴파일 에러 발생 ... 조작할 가능성 때문
228 : static 멤버 변수 ... 객체가 여러개 생성 되어도 하나의 전역 변수 처럼 쓸 수 있다
class Person {
static in count;
}
int Person::count = 1; //static 멤버 초기화 방법. 클래스 밖에서 전역변수 위치에서 실행
229 : static 멤버의 특징
1) main함수 호출전 메모리 공간에 올라서 초기화 됨. 따라서 public 선언이면 객체 생성전 접근 가능
2) 객체의 멤버로 존재하는 것이 아님. 다만 클래스 내에서 직접 접근 권한이 있을 뿐
* static 변수는 메모리의 Heap, Stack이 아닌 데이터 영역에 올라간다
234 : explicit 키워드 ... 묵시적으로 호출되는 것을 방지
235 : mutable ... 상수(const) 선언된 함수에서도 mutable 선언된 변수는 조작이 가능함 [잘 쓰지 않는다]
-------------------------------------------------------------------------------------------------
## 상속의 이해
-------------------------------------------------------------------------------------------------
244 : 상속의 필요성 .. 객체지향에서 중요시 하는 것 중 하나는 요구사항 변화에 따른 프로그램의 유연성이다!
즉, 새로운 클래스가 추가되어도 프로그램의 다른 영역에는 전혀 변경이 없으면 좋겠다!
249 : 상속되는 클래스 (부모) ~ Base클래스
상속하는 클래스 (자식) ~ Derived 클래스 "드라이브~드"
250 : 상속하는 클래스의 객체 생성 및 소멸 과정
1)메모리할당, 이때 상속되는 클래스를 감안해서 메모리 공간 할당
2)derived클래스의 생성자 호출까지만 → 앗 상속받았잖아!!
3)Base클래스 생성자 호출 및 실행
4)Derived클래스의 생성자 실행
class AAA {
AAA(){} //void 생성자
AAA(int k){}
}
class BBB:public AAA {
BBB(){} //void 생성자
BBB(int x){}
}
int main(){
BBB b1; //BBB의 void생성자 호출→AAA의void생성자호출및실행→ BBB의 void생성자실행
BBB b2(10); //BBB의 (x)생성자 호출 →AAA의void생성자호출및실행→ BBB의 (x)생성자실행
}
AAA(int k){} 생성자를 호출하고 싶다면 BBB의 생성자에 멤버이니셜라이저를 해야 한다. 즉,
BBB(int j) : AAA(j) {} //(중요한건 인자j를 BBB의 int j로 받아서 AAA로 넘겨만 주고 있다.)
식으로 바꿔야 BBB b(10) 이라고 초기화를 할경우 AAA의 생성자도 AAA(10)이 호출/실행된다.
class Person {
Person(int _age = 1, char* _name = "noname"){
age = _age;
strcpy(name, _name);
}
}
class Student : public Person {
Student(char* _major) {
strcpy(major, _major);
}
}
이렇게 하고 main에서
Student Kim("Electronics");
라고 하면 Student는 초기화 되나 Person은 그냥 "1","noname" 로만 초기화 됨 따라서
Student(char* _major, int _age, char* _name) : Person(_age, _name) {
strcpy(major, _major);
}
로 하고 main에서 Student Kim("Electronics",23,"Kim JH"); 로 호출하면 _age,_name이 Person에게 넘겨진다.