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

카테고리

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

※ 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 동화다아아

댓글을 달아 주세요

최근에 달린 댓글

최근에 받은 트랙백

글 보관함