일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 시스템프로그래밍
- 수광 소자
- arduino compiler
- WinAPI
- priority_queue
- html
- map
- c++
- 아두이노
- Array
- directx
- Algorithm
- 자료구조
- 아두이노 컴파일러
- Deque
- 라인트레이서
- Arduino
- Visual Micro
- 운영체제
- 통계학
- stl
- list
- vector
- 컴퓨터 그래픽스
- LineTracer
- Stack
- 아두이노 소스
- queue
- C언어
- set
- Today
- Total
Kim's Programming
C++ - 클래스(Class)(1/2) 본문
Class(클래스)
C++의 구조체는 멤버 함수를 포함할 수 있다는 면에서 C의 구조체에 비해 의미가 확장되었습니다. 이형 타입 변수의 집합인 구조체가 스스로 동작을 정의할 수 있다는 것은 중요한 의미가 있으며 객체 지향 구현을 위한 첫 걸음이라고 할 수 있습니다. C++의 창시자인 스트로스트룸은 확장된 의미의 구조체에 새로운 이름을 붙여주었는데 그것도 Class입니다.앞에서 예시로 들었던 구조체의 struct를 class로 바꿔주고 선언문 선두에 public: 액세스 지정을 하면 됩니다.
1 2 3 4 5 6 7 8 | class Position { public: int x; int y; char ch; void OutPosition(); }; | cs |
모든 구조체들을 이렇게 수정하면 잘 실행됩니다. 확장된 구조체와 클래스의 유일한 차이점은 멤버에 대한 디폴트 엑세스 지정뿐입니다. 구조체는 멤버 함수를 가질 수 없는 것으로 흔히들 알 고 있는데 구조체도 멤버 함수, 생성자, 파괴자를 가질 수 있고 상속도 가능하며 클래스가 쓰이는 모든 곳에 쓸 수 있습니다. 단지 엑세스 지정 없이 멤버를 선언할 때 이 멤버에 어떤 엑세스 지정이 적용되는지만 다릅니다. 구조체의 디폴트 액세스 지정은 public이고 클래스의 디폴트 액세스 지정은 private입니다. 클래스는 객체의 안전성을 위해 외부에서 함부로 값을 건드리지 못하도록 멤버를 숨기는 경향이 있는데 비해 구조체는 가급적이면 멤버를 공개하는 경향이 있습니다. 구조체의 디폴트 엑세스 지정이 public일 수 밖에 없는 이유는 C언어는 호환성을 유지해야 하기 떄문입니다. C에서 구조체의 멤버는 외부에서 자유롭게 액세스 할 수 있으므로 C++의 구조체도 당연히 그렇게 해야합니다.
물론 디폴트 값이 그렇게 되는 것이지 명시적인 액세스 지정자를 통해서 멤버의 공개여부를 변경하는 것은 가능합니다. 디폴트 액세스 지정을 private로 바꾼 구조체는 클래스와 동일하며 디폴트 액세스 지정을 public으로 한 지정한 public으로 바꾼 클래스는 구조체와 동일합니다. 이외는 차이점은 없습니다. 클래스에 적용되는 상송, 다형성, 연산자 오버로딩 등 클래스에 적용되는 모든 방식은 똑같습니다. 클래스 선언 문법은 다음과 같습니다. 구조체와 비슷하되 struct라는 키워드를 class라는 키워드로 바꾸고 멤버 중간 중간에 액세스 지정이 오는 것이 다릅니다. 구조체와 마찬가지로 제일 끝에는 세미콜론이 붙어야합니다.
1 2 3 4 5 6 7 | class 클래스이름 { 액세스 지정: 멤버 변수; 멤버 함수; .... }; | cs |
구조체와 마찬가지로 멤버 개수에는 제한이 없고 필요한 만큼 얼마든지 많은 변수와 함수를 멤버로 포함할 수 있습니다. 멤버의 타입의 타입에도 제한이 없습니다. int, long, double 등의 기본형 변수는 물론이며 배열, 구조체 등의 유도형과 다른 클래스형의 변수까지도 멤버로 포함 될 수 있습니다.구조체끼리 중첩이 가능하듯이 클래스끼리도 중첩이 가능하고 열거형 typedef등의 타입 정의도 포함될 수 있습니다. 확장된 구조체와 클래스는 사실상 같지만 관행상 멤버함수를 가지는 경우는 클래스로 선언하는 것이 일반적입니다.
Class(클래스)는 타입
C++에서 구조체의 태그가 타입으로 승격되어 태그로부터 바로 구조체 변수를 선언할 수 있습니다. 구조체가 하나의 타입으로 인정되는 것과 마찬가지로 클래스도 하나의 타입으로 취급됩니다. 클래스의 이름은 int, double, char 같은 기본형 타입과 동등한 자격을 가지며 사용 방법도 똑같습니다. C++은 클래스가 완전한 타입이 되기 위한 여러 가지 언어적 장치(생성자, 연산자 오버로딩 등)을 제공하는데 다음 표로 정리 해보았습니다.
정수형 |
Complex 클래스 |
C++의 관련 문법 |
int i; |
Complex C; |
클래스의 이름이 타입이 같은 자격을 가짐 |
int i=5; |
Complex C(1,0,2.0); |
생성자, 선언과 동시에 초기화 할 수 있음 |
int i=j |
Complex D=C |
복사 생성자가, 같은 타입의 다른 객체로부터 생성됩니다. |
i=j |
D=C |
대입 연산자 |
i+j |
D+C |
연산자 오버로딩 |
i=3.1415 |
Complex C(1.2) |
변환 생성자, 변환 함수 |
3+i |
1.0+C |
전역 연산자 함수와 프렌드 |
이런 여러 가지 문법에 의해 복소수 클래스인 Complex가 int와 완전히 똑같은 자격을 가질 수 있습니다. 세부적인 문법은 차차 나올것이고 다음 예를 보겠습니다.
1 2 3 4 5 6 7 8 9 | class Complex { private: double real; double image; public: 멤버함수; } | cs |
Complex 클래스는 제곱 했을 떄 음수가 되는 복소수를 표현합니다. 복소수는 자연에 실제로 존재하지 않는 허수이지만 과학 계산에는 중간 과정 계싼을 위해 필요합니다. 수학에서 복소수는 보통 a+bi 형태로 표현이 되는데 a는 상수부 b는 허수부라고 합니다. Complex 클래스는 실수부의 값을 가지는 real과 허수부의 값을 가지는 image를 멤버로 가짐으로써 실세계의 복소수를 모델링하며 이 두 멤버의 조합으로 필요한 모든 복소수를 다 표현합니다. Complex 클래스의 멤버함수들은 초기화, 대입, 연산, 출력등의 동작을 할 것입니다.
C/C++언어 차원에서 복소수 타입을 지원하지는 않지만 필요한다면 이런 타입을 클래스로 만들어 사용할 수 있습니다. Complex 클래스는 int와 double과 마찬가지로 변수를 생성할 수 있으며 함수의 인수나 리턴값으로 사용할 수 있습니다. 뿐만아니라 연산자 함수를 작성하면 복소수끼리 더하고 빼고 곱하는 연산도 가능합니다. int double이 올 수 있는 위치면 Complex도 언제나 올 수 있으며 그래서 클래스는 모든 면에서 타입이라고 할 수 있습니다.
C/C++이 클래스를 완전한 타입으로 인정하므로 클래스로부터 유도형 타입을 만들 수도 있습니다. T형이 있을 때 T형 포인터와 T형 배열이 항상 가능하므로 클래스의 배열이나 클래스의 배열을 선언하고 Position형 변수에 대한 포인터로 이 배열을 관리합니다. 다음 소스를 보겠습니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | #include<Windows.h> #include<iostream> #include<time.h> void gotoxy(int x, int y) { COORD pos = { x, y }; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos); } class Position { private: int x; int y; char ch; public: void InitRand() { x = rand() % 80; y = rand() % 24; ch = rand() % (('Z' - 'A' + 1) + 'A'); } void Outposition() { gotoxy(x, y); putchar(ch); } void ErasePostion() { gotoxy(x, y); putchar(' '); } }; void main() { Position arPos[50]; Position *pPos; int i = 0; srand(time(NULL)); for (i = 0; i < sizeof(arPos) / sizeof(arPos[0]); i++) { arPos[i].InitRand(); arPos[i].Outposition(); Sleep(50); } Sleep(1000); pPos = arPos; for (i = 0; i < sizeof(arPos) / sizeof(arPos[0]); i++) { pPos->ErasePostion(); pPos++; Sleep(50); } } | cs |
기존의 Position 클래스에 두 개의 멤버 함수가 추가되었습니다. InitRand함수는 출력할 위치와 문자를 난수로 초기화하고 ErasePosition 함수는 이미 출력되어 있는 문자를 삭제합니다. Position클래스에 난수로 자신을 초기화하는 기능과 이미 출력한 문자를 지우는 기능이 추가되었습니다. main함수의 코드를 분석해 보겠습니다. arPos는 Position형 변수 50개를 담을 수 있는 클래스 배열로 선언되었습니다. 개념적으로 구조체 배열과 동일합니다. 첫 번째 i 루프는 0~49까지 반복하면서 arPos[i]를 난수로 초기화하고 초기화된 arPos[i]의 OutPosition함수를 호출하여 난수 위치에 문자를 출력합니다. 여기까지 실행하면 50개들이 무작위 위치에 출력되어있습니다.
두 번째 i루프애서는 ErasePosition 함수를 호출하여 이미 출력된 문자들을 지우는데 이때는 Position형의 포인터 변수 pPos를 사용했습니다. nPos=arPos 대입문은 pPos에 arPos 배열의 다음 요소로 이동합니다. arPos[0]~arPos[49]까지 루프를 돌면서 ErasePosition 멤버 함수 함수를 호출했으므로 출력된 문자들이 차례대로 사라지게 됩니다.
보다시피 arPos배열이나 pPos 포인터 변수가 동작하는 방식은 int형 배열이나 int *형 변수가 동작하는 방식과 동일합니다. 필요하다면 Position형 포인터 배열이나 Position형 이차 배열, Position형 이중 포인터 들도 만들수 있으며 이때 기존의 C문법이 클래스에 대해서도 일관되게 적용됩니다. 클래스가 완전한 타입이기 떄문입니다.
클래스의 이름은 일종의 명칭이기 떄문에 모델링한 대상을 잘 표현할 수 있는 이름을 자유롭게 붙일 수 있습니다. 이때 명칭이 클래스임을 나타내기 위해서 접두어를 붙이는게 관행입니다. 마이크로소프트는 CString, CObject, CArray등으로 이름 앞에 C를 붙여서 클래스임을 알립니다. 역시나 관행은 관행 꼭 그렇게 이행할 필요는 없습니다.
'Programming > Cplusplus' 카테고리의 다른 글
C++ - 생성자(Constructor) (0) | 2015.08.29 |
---|---|
C++ - 클래스(Class)(2/2) (0) | 2015.08.28 |
C++ - 구조체의 확장 (0) | 2015.08.27 |
C++ 에서의 동적 할당 new/delete (0) | 2015.08.27 |
C++ 입력함수 cin을 사용해보자 (0) | 2015.07.24 |