5 장클래스의활용 클래스와배열객체포인터 this 포인터멤버함수오버로딩디폴트매개변수의사용 friend ( 전역함수, 클래스, 멤버함수 ) 내포클래스지역클래스 static 멤버 const 멤버와 const 객체 explicit 생성자 C++ 프로그래밍입문
1. 클래스와배열 int 형배열선언및초기화 int ary[5] = 1, 2, 3, 4, 5 ; for (int i = 0; i < 5; i++) cout << "ary[" << i << "] = " << ary[i] << endl; 5 장클래스의활용 1
1. 클래스와배열 5 개의 CPoint 형객체원소를갖는배열선언및사용 class CPoint int x, y; 기본적으로는일반변수의배열사용방법과동일! void SetXY(int a, int b) x = a; y = b; void Print() cout << "(" << x << ", " << y << ")" << endl; ; CPoint pt[5]; int i; // 5 개원소를갖는 CPoint 형객체배열 for (i = 0; i < 5; i++) pt[i].setxy(i, i); for (i = 0; i < 5; i++) pt[i].print(); 5 장클래스의활용 2
1. 클래스와배열 객체배열선언시각객체의값을 (0, 0), (1, 1) (4, 4) 로초기화 생성자에주의 class CPoint int x, y; CPoint(int a, int b) : x(a), y(b) void Print() cout << "(" << x << ", " << y << ")" << endl; ; CPoint pt[5] = CPoint(0, 0), CPoint(1, 1), CPoint(2, 2), CPoint(3, 3), CPoint(4, 4) ; // 객체배열선언 & 초기화 for (int i = 0; i < 5; i++) pt[i].print(); 각객체의초기화방법에주의 CPoint P1 = CPoint(1, 1); 과같은형태 CPoint(int, int) 생성자가존재해야함 5 장클래스의활용 3
1. 클래스와배열 객체배열생성및초기화와생성자의사용예 CPoint pt[3] = CPoint(), CPoint(1), CPoint(2, 3) ; 매개변수 0개, int형 1개, int형 2개인생성자가존재해야함 CPoint pt[3] = CPoint(2, 3) ; 매개변수 2개인생성자 매개변수 0개인생성자필요 : 두번째원소부터적용 CPoint pt[3] = 1, 2, CPoint(3, 4) ; 매개변수 int형 1개, int형 2개인생성자필요 매개변수가 1개인경우클래스명생략가능 ü CPoint P1 = 5; 와같은형태임 5 장클래스의활용 4
1. 클래스와배열 2 차원객체배열 : 3 행 2 열 class CPoint int x, y; CPoint(int a, int b) : x(a), y(b) void Print() cout << "(" << x << ", " << y << ")"; ; CPoint pt[3][2] = CPoint(0, 0), CPoint(0, 1), CPoint(1, 0), CPoint(1, 1), CPoint(2, 0), CPoint(2, 1) ; // 2 차원배열 & 초기화 for (int i = 0; i < 3; i++) for (int j = 0; j < 2; j++) pt[i][j].print(); cout << "\t"; cout << endl; 일반변수의초기화개념과동일 5 장클래스의활용 5
2. 객체포인터 int 형변수의동적할당및사용 int *ptr; int i; ptr = new int(3); // 동적생성과동시에초기화가능 cout << *ptr << endl; delete ptr; ptr = new int[5]; // 배열의동적생성은초기화불가능 for (i = 0; i < 5; i++) ptr[i] = i; for (i = 0; i < 5; i++) cout << ptr[i] << endl; delete [] ptr; 배열에대한동적할당의경우 delete [] 사용 5 장클래스의활용 6
2. 객체포인터 class CPoint int x, y; 메모리해제 CPoint() : x(0), y(0) CPoint(int a) : x(a), y(a) CPoint(int a, int b) : x(a), y(b) void SetXY(int a, int b) x = a, y = b; delete ptr; void Print() cout << "(" << x << ", " << y << ")" << endl; ; 클래스객체를동적으로할당받는방법 기본적으로일반변수의동적할당과동일! 객체포인터선언 객체동적생성 CPoint *ptr; ptr = new CPoint; ptr->print(); delete ptr; ptr = new CPoint(); ptr->print(); ptr = new CPoint(1); ptr->print(); delete ptr; 각각의생성자필요 ptr = new CPoint(2, 3); ptr->print(); delete ptr; 5 장클래스의활용 7
2. 객체포인터 객체배열의동적생성 CPoint *ptr; int i; 객체배열을동적으로생성할경우에는매개변수가없는생성자가반드시있어야함 ptr = new CPoint[5]; // 객체포인터를이용한배열동적생성 for (i = 0; i < 5; i++) ptr[i].setxy(i, i); for (i = 0; i < 5; i++) ptr[i].print(); delete [] ptr; 5 장클래스의활용 8
3. this 포인터 객체생성과메모리구조 class CPoint int x, y; CPoint(int a, int b) : x(a), y(b) void Move(int a, int b) x += a; y += b; void Print() cout << "(" << x << ", " << y << ")" << endl; ; CPoint P1(1, 2); CPoint P2(3, 4); P1.Move(1, 1); P2.Move(2, 2); P1.Print(); P2.Print(); 객체에대한멤버변수는별도로생성됨멤버함수는하나만생성, 모든객체가공유 this 포인터!!! 5 장클래스의활용 9
3. this 포인터 this 포인터 멤버함수호출시해당객체에대한주소를받는형식매개변수 멤버함수의개념적구조 class CPoint int x, y; this 포인터를명시적으로사용가능 CPoint(int a, int b) : x(a), y(b) void Move(int a, int b) this->x += a; this->y += b; void Print() cout << "(" << this->x << ", " << this->y << ")" << endl; ; 5 장클래스의활용 10
3. this 포인터 this 포인터에대한원리이해 : 멤버함수를전역함수로만든다면? struct CPoint int x, y; ; 클래스는구조체로 void Move(CPoint *This, int a, int b) This->x += a; This->y += b; 멤버함수는전역함수로해당객체의주소를 This 포인터로받음 void Print(CPoint *This) cout << "(" << This->x << ", " << This->y << ")" << endl; CPoint P1 = 1, 2 ; CPoint P2 = 3, 4 ; Move(&P1, 1, 1); Move(&P2, 2, 2); 함수호출시관련객체의주소를넘김 Print(&P1); Print(&P2); 5 장클래스의활용 11
3. this 포인터 this 포인터의사용예 (1) class CPoint int x, y; CPoint(int a, int b) : x(a), y(b) 함수를호출한객체의 CPoint *MoveX(int a) x += a; return this; 주소를반환 CPoint *MoveY(int b) y += b; return this; void Print() cout << "(" << x << ", " << y << ")" << endl; ; CPoint P1(1, 2); P1.MoveX(3)->MoveY(4); P1.Print(); // MoveX 의결과가 P1 포인터 5 장클래스의활용 12
3. this 포인터 this 포인터의사용예 (2) class CPoint int x, y; CPoint(int a, int b) : x(a), y(b) CPoint &MoveX(int a) x += a; return (*this); // 객체자체반환 CPoint &MoveY(int b) y += b; return (*this); // 객체자체반환 void Print() cout << "(" << x << ", " << y << ")" << endl; ; 함수를호출한객체의참조반환 반환결과자체가그객체가됨 CPoint P1(1, 2); P1.MoveX(3).MoveY(4); // MoveX 결과가 P1 그자체 P1.Print(); this 포인터의실사용예 à 7 장연산자오버로딩! 5 장클래스의활용 13
4. 멤버함수오버로딩 멤버함수의오버로딩가능 class CPoint int x, y; CPoint() : x(0), y(0) CPoint(int a, int b) : x(a), y(b) void Move(int a) x += a; // Move 함수 void Move(int a, int b) x += a; y += b; // Move 함수오버로딩 void Print() cout << "(" << x << ", " << y << ")" << endl; ; CPoint P1(1, 2); P1.Move(3); P1.Move(4, 5); P1.Print(); 5 장클래스의활용 14
5. 디폴트매개변수의사용 멤버함수작성시디폴트매개변수사용가능 class CPoint int x, y; 생성자의디폴트매개변수사용 멤버함수의디폴트매개변수사용 CPoint(int a = 0, int b = 0) : x(a), y(b) void Move(int a, int b = 0) x += a; y += b; void Print() cout << "(" << x << ", " << y << ")" << endl; ; 5 장클래스의활용 15
6. friend 전역함수 private 멤버에대한접근 내부접근만가능 : 해당클래스의멤버함수에의한접근가능 외부접근불가능 예외 : friend 에의한접근가능 friend 선언 특정클래스입장에서다른전역함수, 클래스, 다른클래스의멤 버함수를자신의친구 (friend) 로선언하는것 friend 의종류 friend 전역함수 friend 클래스 friend 멤버함수 class classa func 함수를자신의 friend로선언 int x; friend int func(classa &obja, int a); ; private 멤버에접근가능 int func(classa &obja, int a) obja.x = a; 5 장클래스의활용 16
6. friend 전역함수 예 : friend 전역함수 class CPoint int x; int y; CPoint(int a = 0, int b = 0) : x(a), y(b) ; friend void Center(CPoint P1, CPoint P2); // Center 함수를 friend 로선언 void Center(CPoint P1, CPoint P2) CPoint P; private 멤버에접근가능 P.x = (P1.x + P2.x) / 2; P.y = (P1.y + P2.y) / 2; cout << " 중심 : " << "(" << P.x << ", " << P.y << ")" << endl; CPoint P1(1, 2), P2(3, 4); Center(P1, P2); 5 장클래스의활용 17
6. friend 전역함수 참고사항 friend 함수선언의위치 선언하는영역 (private, public) 과무관하며의미동일 클래스내에서 friend 함수선언시에만 friend 키워드추가 함수정의시에는 friend 키워드가없음 à 함수자체는일반전역함수 friend 선언은멤버함수의선언이아님 단지기존함수에대한 friend 선언일뿐 객체를통한접근불가능 5 장클래스의활용 18
7. friend 클래스 예 : CCar 클래스 ( 자동차 ) 와 CController 클래스 ( 리모콘 ) CController 클래스의멤버함수에서 CCar 클래스객체의 private 에접근 CCar 클래스에서 CController 클래스를 friend 클래스로선언! class CCar friend class CController; ; class CCar bool OnOff; int price; int speed; CCar(int p) : OnOff(false), price(p), speed(0) void PrintSpeed() cout << " 현재속도 : " << speed << endl; ; friend class CController; // friend 클래스선언 5 장클래스의활용 19
7. friend 클래스 코드계속 class CController int price; CController(int p) : price(p) void TurnOn(CCar &car) car.onoff = true; // CCar의 private 접근 void TrunOff(CCar &car) car.onoff = false; void SpeedChange(CCar &car, int v) car.speed += v; ; CCar MyCar(100); CController MyController(10); MyController.TurnOn(MyCar); MyController.SpeedChange(MyCar, 5); MyCar.PrintSpeed(); MyController.TrunOff(MyCar); 5 장클래스의활용 20
class CCar; 7. friend 클래스 : 전방선언 class CController int price; 앞예제에서 CController 클래스를 CCar 클래스앞에위치시킨다면 CController(int p) : price(p) void TurnOn(CCar &car); void TrunOff(CCar &car); void SpeedChange(CCar &car, int v); ; class CCar bool OnOff; int price; int speed; 전방선언 : CCar 클래스의존재를알아야됨사용은불가 ( 예 : car.off) CCar 클래스의사용은 CCar 클래스선언이후에가능 CCar 클래스객체의사용은 CCar 클래스선언이나온이후에가능 à CController 의멤버함수를 CCar 선언이후에작성하였음 void CController::TurnOn(CCar &car) car.onoff = true; void CController::TrunOff(CCar &car) car.onoff = false ; void CController::SpeedChange(CCar &car, int v) CCar(int p) : OnOff(false), price(p), speed(0) void PrintSpeed() cout << " 현재속도 : " << speed << endl; car.speed += v; friend class CController; ; 5장클래스의활용 21
7. friend 클래스 : 전방선언 전방선언이필수적인예 앞예의경우 CCar 클래스를 CController 클래스앞에위치시킨다면전방선언이필요없음 문제 : CCar 클래스의멤버함수로다음과같은함수를추가하였다면? void SetPrice(CController &controller, int p) controller.price = p; CCar, CController 클래스에서서로상대방클래스객체를사용하는경우 전방선언없이해결가능한가? 교재 : 예제 5.17 참고 5 장클래스의활용 22
8. friend 멤버함수 다른클래스의특정멤버함수만을 friend 로선언가능 예 : CController 에서 CCar 의 SetPrice 함수만을 friend 로선언 class CController int price; CController(int p) : price(p) void TurnOn(CCar &car) car.onoff = true; void TrunOff(CCar &car) car.onoff = false; void SpeedChange(CCar &car, int v) car.speed += v; ; friend void CCar::SetPrice(CController &controller, int p); // friend 선언 friend 의사용 정보은닉위배 : 가급적사용을피하는것이바람직 전형적인사용예 : 7.9 절입출력연산자오버로딩 5 장클래스의활용 23
9. 내포클래스선언 내포클래스 (nested class) 다른클래스선언내에선언되어있는클래스 class CCircle class CPoint int x; int y; // 내포클래스 내포클래스가 private 영역에있으므로외부에서는사용불가 à 다음페이지참고 CCircle cir(3, 4, 5); cir.print(); CPoint(int a = 0, int b = 0) : x(a), y(b) void Move(int a, int b) x += a; y += b; void Print() cout << " 중심 : (" << x << ", " << y << ")" << endl; ; CPoint Center; double Radius; // 내포클래스객체를멤버객체로선언 CCircle(int a, int b, double r) : Radius(r) Center.Move(a, b); void Print() Center.Print(); // 멤버객체 Center의사용 cout << " 반지름 : " << Radius << endl; ; 5 장클래스의활용 24
9. 내포클래스선언 내포클래스의사용 class CCircle class CPoint int x; int y; // 내포클래스 CPoint(int a = 0, int b = 0) : x(a), y(b) void Move(int a, int b); void Print(); ; CPoint Center; double Radius; CCircle(int a, int b, double r) : Radius(r) Center.Move(a, b); void Print() Center.Print(); cout << " 반지름 : " << Radius << endl; ; 5 장클래스의활용 25
9. 내포클래스선언 코드계속 void CCircle::CPoint::Move(int a, int b) // 내포클래스멤버함수의외부정의 x += a; y += b; void CCircle::CPoint::Print(void) cout << " 중심 : (" << x << ", " << y << ")" << endl; CCircle cir(3, 4, 5); cir.print(); CCircle::CPoint P2(100, 200); P2.Print(); // 내포클래스객체생성 5 장클래스의활용 26
10. 지역클래스선언 지역클래스 (local class) 함수내부에선언되어있는클래스 멤버함수의내부정의만을허용 ( 외부정의불가 ) 해당함수내에서만사용가능 class CPoint int x, y; // 지역클래스선언, main 함수내에서만사용가능 CPoint(int a, int b) : x(a), y(b) void Print() cout << "(" << x << ", " << y << ")" << endl; ; CPoint P1(1, 2); P1.Print(); 5 장클래스의활용 27
11. static 멤버 static 멤버변수와 static 멤버함수 static 멤버변수 클래스당단하나만생성됨 객체또는클래스명을통해접근가능 ( 단, public인경우에한함 ) 변수생성을위해서는초기화과정필수 static 멤버함수 static 멤버 ( 변수또는함수 ) 에만접근가능 객체또는클래스명을통해접근가능 ( 단, public인경우에한함 ) 5 장클래스의활용 28
11. static 멤버 예 : 현재생성되어있는객체의개수 class CPoint int x, y; static int count; // static 멤버변수 CPoint(int a = 0, int b = 0) : x(a), y(b) count++; ~CPoint() count--; void Print() cout << "(" << x << ", " << y << ")" << endl; static int GetCount() return count; // static 멤버함수 ; int CPoint::count = 0; // 초기값이없을경우 0 으로초기화 CPoint P1(1, 2); CPoint *P2 = new CPoint(3, 4); static 멤버변수의초기화과정필수 cout << "count : " << CPoint::GetCount() << endl; delete P2; cout << "count : " << P1.GetCount() << endl; // static 함수호출 5 장클래스의활용 29
12. const 멤버와 const 객체 const 멤버변수와 const 멤버함수 const 멤버변수 : 객체생성과동시에초기화필요 멤버초기화구문사용 const 멤버함수 : 멤버변수의값을읽을수있으나변경불가능 멤버변수의주소반환불가. 비 const 멤버함수의호출불가. class CCircle double Radius; const double PI; CCircle(double r = 0) : Radius(r), PI(3.14) // const 변수 PI 초기화 void SetRadius(double r) Radius = r; double GetArea() const return (PI * Radius * Radius); // const 함수 ; CCircle Cir1(1); cout << " 면적 : " << Cir1.GetArea() << endl; 5 장클래스의활용 30
12. const 멤버와 const 객체 const 객체 객체생성시 const 접두사추가 멤버변수의값변경불가 const 멤버함수이외의멤버함수에대한호출불가 const CCircle Cir1(1); // const 객체 // Cir1.SetRadius(2); // X, 비const 함수호출불가 cout << " 면적 : " << Cir1.GetArea() << endl; // const 함수호출가능 5 장클래스의활용 31
13. explicit 생성자 explicit 생성자 생성자앞에 explicit 키워드추가 묵시적형변환에의한객체생성불가 class CNumber int x; CNumber() : x(0) ; explicit CNumber(int a) : x(a) ; CNumber N1; CNumber N2(1); CNumber N3 = CNumber(2); CNumber N4 = 3; // Ok! // Ok! // Ok! // No! 불가능 3 à CNumber(3) 묵시적형변환 5 장클래스의활용 32