본문 바로가기

C 언어/C++

c++ 기초단계 (11/14)

HUD(head-up display)

  - 조종사가 전방을 향한채 필요한 데이터를 읽을 수 있는 장치

 

자바는 객체를 물려받는게 1개로 한정(단일 상속)

c++은 객체를 물려받는게 여러개(다중 상속)

 

다중상속하기 예

  1: //다중상속
  2: #include <iostream.h>
  3: #include <stdio.h>
  4: #include <stdlib.h>
  5: #include <string.h>
  6: 
  7: class audio    //클래스
  8: {
  9:     char *cpMaker;        //오디오제조사
 10: 
 11:     public :    //내외부 접근가능
 12:         int a;
 13:         audio()        //생성자
 14:         {
 15:             cpMaker = 0;
 16:             cout << "audio 디폴트생성자" << endl;
 17:         }
 18: 
 19:         audio(char *cpMaker)    //this -> cpMaker가 클래스 cpMaker
 20:         {
 21:             unsigned int uiLen;
 22: 
 23:             this -> cpMaker = 0;    //객체자체가 자기자신 가리키는 포인터(this ->)
 24:             uiLen = strlen(cpMaker);
 25:             this -> cpMaker = (char*)malloc(uiLen);
 26:             strcpy(this -> cpMaker, cpMaker);    //cpMaker를 객체cpMaker복사
 27:             
 28:             cout << "audio 노디폴트생성자 호출 " << " " << this -> cpMaker << endl;
 29:         }
 30:     
 31:         ~audio()
 32:         {
 33:             if(0 != cpMaker)
 34:             {
 35:                 free(cpMaker);    
 36:             }
 37:             cout << "audio 소멸자" << endl;
 38:             
 39:         }
 40: };
 41: 
 42: class car
 43: {
 44:     protected :        //상속받은애만 사용할수 있음
 45:         int uiSpeed;        //속도변수
 46: 
 47:     private :    //내부에서만 접근가능속성
 48:         unsigned int uiNumber;
 49:         unsigned char *ucpVendor;    //차 제조사
 50: 
 51:     //생성자를 오버로딩
 52:     public :    
 53:         int c;
 54:         car()    //자료형이 없는 함수(생성자)    ,디폴트 생성자
 55:         {
 56:             uiNumber = 0;
 57:             ucpVendor = 0;
 58:             cout << "car 디폴트생성자 호출" << endl;
 59:         }
 60:     
 61: //    public :    //public을 디폴트 생성자 다음으로 옴겨봄
 62:         car(unsigned int uiNumber)    //디폴트 생성자가 아님    
 63:         {
 64:             ucpVendor = 0;
 65: 
 66:             this -> uiNumber = uiNumber;
 67:             cout << "uiNumber car 생성자 호출 " << uiNumber << endl;
 68:         }
 69: 
 70: //    public :
 71:         car(unsigned int uiNumber, char* cpVendor)    //디폴트 생성자가 아님    
 72:         {
 73:             unsigned int uiLen;
 74:     
 75:             uiLen = strlen(cpVendor);
 76:             ucpVendor = (unsigned char*)malloc(uiLen);
 77:             strcpy((char*)ucpVendor, cpVendor);
 78:             
 79:             this -> uiNumber = uiNumber;
 80:             cout << "uiNumber car 생성자 호출 " << this -> uiNumber << " " << cpVendor << endl;
 81:         }
 82: 
 83:         ~car()    //틸드붙인거(소멸자)        
 84:         {
 85:             if(0 != ucpVendor)
 86:             {
 87:                 free(ucpVendor);
 88:             }
 89:             cout << "car 소멸자 호출 " << uiNumber << endl;
 90:         }
 91:         
 92: };
 93: 
 94: class audi:public car,public audio    //상속(extends 뒤 콤마(,)로 계속 쓸수있는 다중상속)
 95: {
 96:     public :
 97:         int k;
 98:         audi()
 99:             :car(1234, "Germany"),audio("JBL")    //인자있는 디폴트생성자
100:         {
101:             c = 100;    //여기서는 상속받아서 에러가 안일어난다.
102:             cout << "audi가 생성되었습니다 " << endl;
103:             uiSpeed = 0;
104:         }
105:         ~audi()
106:         {
107:             cout << "audi가 소멸되었습니다 " << endl;
108:         }
109: 
110:         void SpeedUp()    //속도업
111:         {
112:             uiSpeed = uiSpeed + 10;
113:             
114:             if(uiSpeed > 100)
115:             {
116:                 uiSpeed = 100;
117:             }
118:             cout << "지금 속도는 " << uiSpeed << "km/h 입니다" << endl;
119:         }
120: 
121:         void SpeedDown()    //속도다운
122:         {
123:             uiSpeed = uiSpeed - 10;
124: 
125:             if(uiSpeed < 0)
126:             {
127:                 uiSpeed = 0;
128:             }
129:             cout << "지금 속도는 " << uiSpeed << "km/h 입니다" <<endl;
130:         }
131: };
132: 
133: int main()
134: {
135:     unsigned char ucVal;
136:     audi obj;
137:     obj.k = 100;
138:     obj.c = 100;    //접근불가에러
139:     obj.a = 100;    //car앞에만 public 에러, public audio 따로 적용(멤버개념)
140: //    audio obj1;
141: //    audio obj2 = "짝꿍";
142:     
143:     while('q' != ucVal)    //q 입력시 종료
144:     {
145:         cout << "명령을 입력하시오" << endl;
146:         cin >> ucVal;        // scanf와 같은 입력기능
147: 
148:         if('u' == ucVal)    //u키 입력시
149:         {
150:             obj.SpeedUp();    //SpeedUp함수 호출
151:         }
152: 
153:         else if('d' == ucVal)    //d키 입력시
154:         {
155:             obj. SpeedDown();    //SpeedDown함수 호출
156:         }
157:         
158:     }
159: 
160:     return 0;
161: }
162: 

 

audi : car, audio로 할 시

앞에 있는 클래스가 제일 먼저 생성되며 제일 나중에 소멸된다.

uiNumber car 생성자

audio 디폴트생성자

audi 생성자

audi 소멸자

audio 소멸자

car 소멸자

 

audi : audio, car로 할 시

audio 디폴트생성자

uiNumber car 생성자

audi 생성자

audi 소멸자

car 소멸자

audio 소멸자

 

위로 본 결과 순서에 상관이 있다는걸 확인할 수 있다.

 

derivation – 유도

composition – 구성

 

상속을 유도라 할 수 있다.

예) 나는 부모님으로부터 유도되었다.(상속)

 

image image

 

참고

 

main함수에서

138:     obj.c = 100;    //접근불가에러

입력시 에러가 발생하는데

main입장에선 상속을 받을 때 private인지 public인지 결정을 못하는상태?라서 에러가 출력하는것이다.

아래처럼

 94: class audi:public car,public audio    //상속(extends 뒤 콤마(,)로 계속 쓸수있는 다중상속)

car앞에 public을 입력해주면 main이 결정을 해서 컴파일이 잘된다.

그리고 audio도 마찬가지로 앞에 public을 따로 입력해줘야한다. 이는 멤버개념이라서 그런 것이다.

 

다중상속에서 test()를 한번 호출해보았다(오버로딩식으로)

  1: //다중상속 test()호출
  2: #include <iostream.h>
  3: #include <stdio.h>
  4: #include <stdlib.h>
  5: #include <string.h>
  6: class audio  //클래스
  7: {
  8: char *cpMaker;    //오디오제조사
  9: public :  //내외부 접근가능
 10: int a;
 11:     audio()    //생성자
 12:     {
 13:       cpMaker = 0;
 14:     }
 15:     audio(char *cpMaker)  //this -> cpMaker가 클래스 cpMaker
 16:     {
 17: unsigned int uiLen;
 18: this -> cpMaker = 0;  //객체자체가 자기자신 가리키는 포인터(this ->)
 19:       uiLen = strlen(cpMaker);
 20: this -> cpMaker = (char*)malloc(uiLen);
 21:       strcpy(this -> cpMaker, cpMaker);  //cpMaker를 객체cpMaker복사
 22:     }
 23:     ~audio()
 24:     {
 25: if(0 != cpMaker)
 26:       {
 27:         free(cpMaker);  
 28:       }
 29:     }
 30: void test(float)
 31:     {
 32:       cout << "audio test() 호출" << endl;
 33:     }
 34: };
 35: class car
 36: {
 37: protected :    //상속받은애만 사용할수 있음
 38: int uiSpeed;    //속도변수
 39: private :  //내부에서만 접근가능속성
 40: unsigned int uiNumber;
 41: unsigned char *ucpVendor;  //차 제조사
 42: //생성자를 오버로딩
 43: public :  
 44: int c;
 45:     car()  //자료형이 없는 함수(생성자)  ,디폴트 생성자
 46:     {
 47:       uiNumber = 0;
 48:       ucpVendor = 0;
 49:     }
 50:     car(unsigned int uiNumber)  //디폴트 생성자가 아님  
 51:     {
 52:       ucpVendor = 0;
 53: this -> uiNumber = uiNumber;
 54:     }
 55:     car(unsigned int uiNumber, char* cpVendor)  //디폴트 생성자가 아님  
 56:     {
 57: unsigned int uiLen;
 58:       uiLen = strlen(cpVendor);
 59:       ucpVendor = (unsigned char*)malloc(uiLen);
 60:       strcpy((char*)ucpVendor, cpVendor);
 61: this -> uiNumber = uiNumber;
 62:     }
 63:     ~car()  //틸드붙인거(소멸자)    
 64:     {
 65: if(0 != ucpVendor)
 66:       {
 67:         free(ucpVendor);
 68:       }
 69:     }
 70: void test(char)
 71:     {
 72:       cout << "car test() 호출" << endl;
 73:     }
 74: };
 75: class audi:public car,public audio  //상속(extends 뒤 콤마(,)로 계속 쓸수있는 다중상속)
 76: {
 77: public :
 78: int k;
 79:     audi()
 80:       :car(1234, "Germany"),audio("JBL")  //인자있는 디폴트생성자
 81:     {
 82:       c = 100;  //여기서는 상속받아서 에러가 안일어난다.
 83:       uiSpeed = 0;
 84:     }
 85:     ~audi()
 86:     {
 87:     }
 88: void SpeedUp()  //속도업
 89:     {
 90:       uiSpeed = uiSpeed + 10;
 91: if(uiSpeed > 100)
 92:       {
 93:         uiSpeed = 100;
 94:       }
 95:     }
 96: void SpeedDown()  //속도다운
 97:     {
 98:       uiSpeed = uiSpeed - 10;
 99: if(uiSpeed < 0)
100:       {
101:         uiSpeed = 0;
102:       }
103:     }
104: void test(int)
105:     {
106:       cout << "audi test() 호출" << endl;
107:     }
108: };
109: int main()
110: {
111: unsigned char ucVal;
112:   audi obj;
113:   obj.k = 100;
114:   obj.c = 100;  //접근불가에러
115:   obj.a = 100;  //car앞에만 public 에러, public audio 따로 적용(멤버개념)
116:   obj.test('a');
117:   obj.audio::test(3.55f);
118: // c++는변수를 아무곳에서나 쓸 수 있다.
119:   audi* p;
120:   p = &obj;
121:   p -> test(3);  //audi test()호출
122:   car* p2;
123:   p2 = &obj;
124:   p2 -> test(3);  //car test()호출
125: return 0;
126: }
127: 

 

116:   obj.test('a');

을 입력시 당연히 인자가 char인 car test()를 호출할 것이라 예상했으나..

최근에 호출한 audi test() 호출이 되었다.

 

car test()를 호출하기 위해서는

obj.car::test(‘a’)를 입력해야 한다.

 

  1: #if 0 
  2: #include <stdio.h>
  3: #else
  4: #include <iostream.h>
  5: #endif
  6: #include <stdlib.h>
  7: #include <string.h>
  8: 
  9: class object
 10: {
 11: //    private :
 12:     public:
 13:         unsigned char *ucpType;
 14: 
 15: //    public:        //object 생성자 호출
 16:     private :    
 17:         object()
 18:         {
 19:             cout << "object 디폴트생성자" << endl;
 20:         }
 21:     protected :
 22:         object(unsigned char *ucpType)
 23:         {
 24:             this -> ucpType = 0;
 25:             if(0 == ucpType)
 26:             {
 27:                 return;
 28:             }
 29:             
 30:             strlen((char*)ucpType);
 31:             this -> ucpType = (unsigned char*)malloc(strlen((char*)ucpType));
 32:             strcpy((char*)this -> ucpType,(char*) ucpType);
 33:             cout << "object 생성자 "<< this -> ucpType << endl;
 34:             
 35:         }
 36:         ~object()
 37:         {
 38:             if(0 != ucpType)
 39:             {
 40:                 free(ucpType);
 41:             }
 42:             cout << "object 소멸자 " << this -> ucpType<< endl;
 43:         }
 44: };
 45: 
 46: class human : public object
 47: {
 48:     public :
 49:          human()
 50:             :object((unsigned char*)"human")
 51:         {
 52:             cout << "human 디폴트생성자"<< endl;
 53:         }
 54:         ~human()
 55:         {
 56:             cout << "human 소멸자"<< endl;
 57:         }
 58:         
 59:         void test()
 60:         {
 61:             cout << "윤수영" <<endl;
 62:         }
 63: 
 64: };
 65: 
 66: class dog : public object
 67: {
 68:     public :
 69:          dog()
 70:             :object((unsigned char*)"dog")
 71:         {
 72:             cout << "dog 디폴트생성자" << endl;
 73:         }
 74:         ~dog()
 75:         {
 76:             cout << "dog 소멸자" << endl;
 77:         }
 78: 
 79:         void test()
 80:         {
 81:             cout << "코커스패니얼" <<endl;
 82:         }
 83: 
 84: };
 85: 
 86: int main()
 87: {
 88: //object obj;        //저는 protected 중
 89:     cout << "-------- human 생성자 호출 ---------" << endl;
 90:     human man;
 91:     cout << "--------- dog 생성자 호출 ----------" << endl;
 92:     dog dog1;
 93:     cout << "--------------------------" << endl;
 94:     
 95:     int    iCnt;
 96:     object *array[] = {&man,&dog1};
 97:     for(iCnt=0; iCnt<2; ++iCnt)
 98:     {
 99:         cout << array[iCnt] -> ucpType << endl;
100:     }
101:     
102:     cout << "--------------------------" << endl;
103: //    k7.test();    //test
104: //    k5.test();
105:     return 0;
106: }

 

 

image

 

여기서 중요한 점은 c++은 human따로 dog 따로 자료형을 만들어 줄 필요 없이 자동으로 object로 타입으로 캐스트 된다.

object 포인터를 쓰면 따로 human이나 dog나 포인터를 따로 해 줄 필요가 없다.

c에서는 일일히 다 해줘야하지만 c++은 이런 것이 허용된다.

 

자바나 MFC등 최상위 클래스는 object이다. (c로 치면 void *와 비슷)

하지만 c++는 그렇지 않다. c를 기반으로 만들어진 언어이기에 object가 최상위라 할 수 없다.

'C 언어 > C++' 카테고리의 다른 글

c++ 기초단계 (11/22)  (1) 2011.11.23
c++ 기초단계 (11/21)  (0) 2011.11.21
c++ 기초단계 (11/18)  (0) 2011.11.18
c++ 기초단계 (11/16)  (0) 2011.11.16
c++ 기초단계 (11/15)  (0) 2011.11.15