블로그 이미지
하루, 글. 그림. 영상매체. 표현을 도와주는 기기들. 도전 중. 동화다아아
    동화다아아

    카테고리

    분류 전체보기 (176)
    잡담 (1)
    IT 기기-리뷰&뉴스 (7)
    리뷰 - 도서 (1)
    리뷰 - 영상 (0)
    리뷰 - 그림/음악 (1)
    내장형 하드웨어 (163)
    Total
    Today
    Yesterday

    ※ HUD(Head Up Display)
     → 유리 등에 화면이 출력되는 것.
     → 처음 비행기에 적용되었고, BMW의 상위 차량 등에 소수 사용되고 있는 것을 확인할 수 있다.


    - car class에 오디오 속성 적용
     → 자바는 객체를 물려 받는 걸 하나로 제한한다.(단일 상속)
     → C++은 객체를 물려 받는 것을 여러개 허용(다중 상속)
     → 생성 순서(어느 객체가 먼저 생성되고 소멸되는지) 등을 명확히 확인해서 에러 해결에 이용한다.( → 프로그램을 짤 때 원인을 알아야만 한다.)
     → C++은 다중 상속을 지원한다.(class K5: car, audio)
     → derivation (유도, 도출, 미분...) 여기서는 유도의 뜻을 가지며 상속을 유도라 한다.
     → composition(구성)
     → 유도(부모 A, 자식 C), C가 A로 부터 상속 받았다.(유도 되었다.)
     → 예제

    #if 1
    #include<iostream.h>
    #include<stdlib.h>
    #else
    #include<stdio.h>
    #endif

    void test();

    // 자동차 클래스
    class car
    {  
      // 클래스 내에서만 사용할 수 있다.
      private:
        unsigned int uiNumber; // 자동차 일련 번호
        unsigned char* ucpVendor; // 제조사
        
        // 생성자 - 자동 호출 된다.(반환형이 없는 특수한 경우)
        // 객체를 생성할 때 만들어 진다.
        // 생성자는 여러개를 만들 수 있으나 소멸자는 하나만 만들 수 있다.
        car() // 인자가 없는 생성자를 디폴트 생성자라 한다.
        {
          uiNumber = 0;
          ucpVendor = 0;
          cout << "Car class 생성자 호출" << endl;
        }  
        car(unsigned int uiNumber) // 자동차 일련번호
        {
          ucpVendor = 0;
          (*this).uiNumber = uiNumber;
          cout << this->uiNumber << " Car class 생성자 호출" << endl;
        }
      // 전체가 사용할 수 있다.
      public:
        int C;
      // 상속 받은 클래스만 사용할 수 있다.
      protected:
        unsigned int uiSpeed;
        // 제조사
        car(unsigned int uiNumber, char *cpVendor)
        {
          unsigned int uiLen; // 길이를 받기 위해
          
          uiLen = strlen(cpVendor);
          ucpVendor = (unsigned char*)malloc(uiLen+1); // NULL을 위해 +1
          strcpy((char *)ucpVendor,cpVendor);
          
          (*this).uiNumber = uiNumber;
          cout << this->uiNumber << cpVendor<< " Car class 생성자 호출" << endl;
        }
        ~car() // 소멸자 - 앞에 틸드(~)를 붙인다. main함수가 종료되기 전에 호출된다.
        {      
          if(0 !=  ucpVendor)  
          {
            free(ucpVendor);
          }
          cout << uiNumber << " CAR class 소멸자 호출" << endl;
        }    
    };
    // 오디오 클래스
    class audio
    {
      private:
      char *cpMaker;
      public:
        int A;
        audio() // 생성자
        {
          cpMaker = 0;
          cout << "audio class" << endl;
        }
        audio(char *cpMaker) 
        {
          unsigned int uiLen; // 길이를 받기 위해

          uiLen = strlen(cpMaker);
          this->cpMaker = (char*)malloc(uiLen+1); // NULL을 위해 +1
          
          strcpy((*this).cpMaker, cpMaker);
          cout << this->cpMaker << " Audio class 생성자 호출" << endl;
        }    
        ~audio() // 소멸자
        {
          if(0 != cpMaker)
          {
            free(cpMaker);
          }
          cout << this->cpMaker << " Audio class 소멸자 호출" << endl;
        }
    };
    // public을 붙여주지 않으면 기본적으로 상속은 private이 된다.
    // 따라서 main()에서 호출하면 접근속성 제한이 되어 사용할 수 없다.
    // 즉, public car로 사용하므로써 main에서 int C; 에 접근 가능하다.
    class K5:public car, public audio // car 클래스의 public을 상속 받는다.
    {
      public:
        int K;
        K5() // 생성자
        :car(1234"KIA"), audio("JBL"// 다중 상속 받았을 때 생성자 구동
        {
          C = 100// 상속 받았으므로 에러가 아니다.(public이므로)
          cout << "(생성자)K5가 생성되었습니다." << endl;

          uiSpeed = 0;
          //uiNumber = 7; // private이므로 에러
        }
        ~K5(void// 소멸자
        {
          cout << "(소멸자)K5가 소멸되었습니다." << endl;
        }
        void speedUp(void)
        {
          uiSpeed = uiSpeed+10;
          if(100<uiSpeed)
          {
            uiSpeed = 100;
          }
          cout << "지금 속도는 " << uiSpeed << "Km입니다." << endl;
          return ;
        }
        void speedDown(void)
        {
          if(0==uiSpeed)
          {
            uiSpeed = 0;
          }
          else
          {
            uiSpeed = uiSpeed-10;
          }
          cout << "지금 속도는 " << uiSpeed << "Km입니다." << endl;
        }
    };
      
    int main()
    {
      unsigned char ucVal;
      K5 OBJ;  
      OBJ.K = 100;
      OBJ.C = 100// public으로 상속받았으므로 메인에서 접근 가능
      OBJ.A = 100;
      cout << "K : " << OBJ.K << ", C : " << OBJ.C << ", A : " << OBJ.A << endl;
      
      // OBJ2.uiSpeed = 100;// protected라 상속 클래스에서만 사용 가능
      while('q' != ucVal)
      {
        cout << "------------------------------" << endl;  
        cout << "명령을 입력하시오" << endl;  
        cin >> ucVal;
        if('u' == ucVal)
        {
          OBJ.speedUp();
        }
        if('i' == ucVal)
        {
          OBJ.speedDown();
        }
      }
      cout << "------------------------------" << endl;  
        
      return 0;
    }

    - 상속받은 변수의 main()에서의 사용
     → ,(컴마)를 사용하므로써 다중 상속이 가능하다.
     → 상속 받은 변수의 접근 속성을 지정해 주지 않으면 기본적으로 private이 되어 main()에서 접근되지 않는다. 따라서 public으로 k5가 상속 받아야 사용할 수 있다. 

    class K5:public car, public audio // car 클래스의 public을 상속 받는다.


     →  함수 오버로딩

    #if 1
    #include<iostream.h>
    #include<stdlib.h>
    #else
    #include<stdio.h>
    #endif

    void test();

    // 자동차 클래스
    class car
    {  
      // 클래스 내에서만 사용할 수 있다.
      private:
        unsigned int uiNumber; // 자동차 일련 번호
        unsigned char* ucpVendor; // 제조사
        
        // 생성자 - 자동 호출 된다.(반환형이 없는 특수한 경우)
        // 객체를 생성할 때 만들어 진다.
        // 생성자는 여러개를 만들 수 있으나 소멸자는 하나만 만들 수 있다.
        car() // 인자가 없는 생성자를 디폴트 생성자라 한다.
        {
          uiNumber = 0;
          ucpVendor = 0;
          //cout << "Car class 생성자 호출" << endl;
        }  

        car(unsigned int uiNumber) // 자동차 일련번호
        {
          ucpVendor = 0;
          (*this).uiNumber = uiNumber;
          //cout << this->uiNumber << " Car class 생성자 호출" << endl;
        }
      // 전체가 사용할 수 있다.
      public:
        int C;
        void test(char)
        {
          cout << "car class test()" << endl;
        }
      
      // 상속 받은 클래스만 사용할 수 있다.
      protected:
        unsigned int uiSpeed;
        // 제조사
        car(unsigned int uiNumber, char *cpVendor)
        {
          unsigned int uiLen; // 길이를 받기 위해
          
          uiLen = strlen(cpVendor);
          ucpVendor = (unsigned char*)malloc(uiLen+1); // NULL을 위해 +1
          strcpy((char *)ucpVendor,cpVendor);
          
          (*this).uiNumber = uiNumber;
          //cout << this->uiNumber << cpVendor<< " Car class 생성자 호출" << endl;
        }
        ~car() // 소멸자 - 앞에 틸드(~)를 붙인다. main함수가 종료되기 전에 호출된다.
        {      
          if(0 !=  ucpVendor)  
          {
            free(ucpVendor);
          }
          //cout << uiNumber << " CAR class 소멸자 호출" << endl;
        }    
    };
    // 오디오 클래스
    class audio
    {
      private:
        char *cpMaker;
        
      public:
        int A;
        audio() // 생성자
        {
          cpMaker = 0;
          //cout << "audio class" << endl;
        }
        // 인자의 타입만 쓸수도 있다.(C와의 차이점)
        audio(char *cpMaker) 
        {
          unsigned int uiLen; // 길이를 받기 위해

          uiLen = strlen(cpMaker);
          this->cpMaker = (char*)malloc(uiLen+1); // NULL을 위해 +1
          
          strcpy((*this).cpMaker, cpMaker);
          //cout << this->cpMaker << " Audio class 생성자 호출" << endl;
        }    
        ~audio() // 소멸자
        {
          if(0 != cpMaker)
          {
            free(cpMaker);
          }
          //cout << this->cpMaker << " Audio class 소멸자 호출" << endl;
        }
        void test(float)
        {
          cout << "audio class test()" << endl;
        }
    };

    // public을 붙여주지 않으면 기본적으로 상속은 private이 된다.
    // 따라서 main()에서 호출하면 접근속성 제한이 되어 사용할 수 없다.
    // 즉, public car로 사용하므로써 main에서 int C; 에 접근 가능하다.
    class K5:public car, public audio // car 클래스의 public을 상속 받는다.
    {
      public:
        int K;
        K5() // 생성자
        :car(1234"KIA"), audio("JBL"// 다중 상속 받았을 때 생성자 구동
        {
          C = 100// 상속 받았으므로 에러가 아니다.(public이므로)
          //cout << "(생성자)K5가 생성되었습니다." << endl;

          uiSpeed = 0;
          //uiNumber = 7; // private이므로 에러
        }
        ~K5(void// 소멸자
        {
          //cout << "(소멸자)K5가 소멸되었습니다." << endl;
        }
        void speedUp(void)
        {
          uiSpeed = uiSpeed+10;
          if(100<uiSpeed)
          {
            uiSpeed = 100;
          }
          //cout << "지금 속도는 " << uiSpeed << "Km입니다." << endl;
          return ;
        }
        void speedDown(void)
        {
          if(0==uiSpeed)
          {
            uiSpeed = 0;
          }
          else
          {
            uiSpeed = uiSpeed-10;
          }
          //cout << "지금 속도는 " << uiSpeed << "Km입니다." << endl;
        }
        void test(int )
        {
          cout << "K5 class test()" << endl;
        }
    };

    int main()
    {
      unsigned char ucVal;
      K5 OBJ;  
      K5 *P;
      P = &OBJ; 
      P->test(3); // C에서의 포인터 사용과 같다.
      car *P2;
      P2 = &OBJ; // OBJ는 K5 타입, P2는 car* 타입
            // K5는 car도 상속받고 있으므로 타입의 문제가 없다.
      P2->test(3); // 객체는 K5이지만 포인터가 car 이므로
            // car의 test()가 호출된다.
      
      OBJ.K = 100;
      OBJ.C = 100// public으로 상속받았으므로 메인에서 접근 가능
      OBJ.A = 100;
      // 함수 오버로딩 - 가장 최근 함수만 호출되도록 되어 있다.
      OBJ.test('A');
      // K5이외의 호출은 스코프 연산자를 사용해야 한다.
      OBJ.audio::test((float)3.5f);
      
      
      cout << "------------------------------" << endl;  
      
      return 0;
    }

     → 가장 최근의 함수만 호출된다.
     → 즉, K5 이외의 함수 호출은 scope 연산자를 사용해야만 한다.

     → class도 일종의 자료타입 -> 객체
     → object, Human, Dog 3개의 클래스를 만들고 object 클래스로부터 Human, Dog 클래스가 상속받는다.
     → object 클래스는 char *type으로 변수를 선언하고 protected 속성으로 상속 클래스 이외의 접근을 막는다.
     → 소스 작성

    #include<iostream.h>
    #include<stdlib.h>


    class object
    {
      private:
        object() // 어차피 생성 안된다.
        {
          cout <<"object class 생성" << endl;
        }
      public:
        char *type;
        
      protected:
        unsigned int uiLen;
        object(char *type)
        {
          if(0 == type)
          {
            this->type = 0;
            return ;
          }
          uiLen = strlen(type);
          this->type = (char*)malloc(uiLen+1);
          strcpy(this->type, type);
          cout << this->type << endl;
        }
        ~object()
        {      
          cout << "object class 소멸" << endl;
        }
    };
    class Human: public object
    {
      private:

      public:
        Human()
        :object("Human")
        {
          cout << "Human class 생성" << endl;
        }
        ~Human()
        {
          cout << "Human class 소멸" << endl;
        }
    };
    class Dog: public object
    {
      private:
        
      public:
        Dog()
        :object("Dog")
        {
          cout << "Dog class 생성" << endl;
        }
        ~Dog()
        {
          cout << "Dog class 소멸" << endl;
        }
      
    };

    int main()
    {
      Human Man;
      Dog dog1;
      object* array[] = {&Man, &dog1};
      
      for(int iCnt = 02>iCnt ; ++iCnt)
      {
        cout << array[iCnt]->type << endl;      
      }  

      return 0;
    }
     

     → object *를 선언하므로써 Human* 타입과, Dog* 타입을 각각 따로 만들 필요 없이 사용할 수 있다.
     → 부모 클래스인 object *는 두 타입을 모두 포함하므로 따라서 각각의 클래스가 많아져 타입이 늘어나더라도 object *로 묶어서 사용할 수 있다.

    object* array[] = {&Man, &dog1};
      
      for(int iCnt = 02>iCnt ; ++iCnt)
      {
        cout << array[iCnt]->type << endl;      
      }  

     → 실행 결과

     → 즉, 위와 같이 서로 다른 두 타입을 object *로 묶어서 배열로 선언하고 for문을 이용하여 출력하였다.
     → 이 방법을 사용하면 다양한 타입을 통일하여 사용할 수 있으므로 타입이 많을 경우 매우 유리하다.
     → 자바는 모조리 상속 받아서 최상위 객체가 존재하고 이것이 object 객체이며 void *와 같다.
     → mfc 등도 object 클래스를 가지나 예외가 존재하며 C++은 C를 포함하기 위해 조금 더 복잡한 구조를 가져 object 객체가 없으나 void *를 직접 쓸 수 있다.
     

     
    Posted by 동화다아아
    , |

    최근에 달린 댓글

    최근에 받은 트랙백

    글 보관함