본문 바로가기
코스웨어/11년 내장형하드웨어

[내장형]윤병도_11월 11일 oop일일보고서

by 알 수 없는 사용자 2011. 11. 14.
728x90
반응형

*두 클래스이상으로 부터 상속받는 클래스 (다중상속)
K5차를 구현할때 car클래스의 속성과 오디오의 속성을 동시에 물려받는 클래스를 만들어 보자
자바의 경우에는 하나의 객체는 하나로부터의 상속을 허용하지만 c++은 다중상속을 허용한다
먼저 audio 클래스를 만들자
class audio
{
  char * maker;  
  public:
    audio()
    {
      cout<< "Audio default constructor called"<<endl;
    }
    audio(char* maker)
    {
      unsigned int uiLen;
      uiLen = strlen((char *)maker);
      this -> maker = (char*)malloc(uiLen+1);
      strcpy(this->maker,maker);
    
      cout<<"Audio non-default constructor called and ";
      cout<<"Audio name is "<<this->maker<<endl;
    
    }
    ~audio()
    {
      cout<<"Audio destructor called"<<endl;
      if(maker != 0)
      {
        free(maker);
        maker = 0;
      }
    }
};

다음 K5클래스에 car와 audio클래스를 동시에 상속하자
class  K5: car ,audio
실행해보면 (k5객체를 만들면 ) 부모 클래스를 적어준 순서대로 생성자가 불림을 알 수 있다
- 객체 생성의 순서가 나중에 문제가 생기는 원인이 되기도 함
*다중상속시 인자있는 부모생성자를 부르는 방법
K5() : car(3,"kia"),audio("jbl");
자식 생성자옆에 인자있는 부모생성자를 적어준다

*UML
상속관계를 나타내는 UML을 그릴때 상속받은 자식과 상속한 부모사이는 화살표로 나타낸다
car <- k5
다중상속에 대한 UML


*부모의 public멤버변수를 main에서 구현한 자식객체에서 접근하기
다음과 같이 코딩하면 멤버변수c때문에 에러가 난다 그 이유는 k5는 상속은 받았지만 그 상속받은 멤버변수
c에 대한 아무런 언급이 없었기때문에 c를 private로 생각하고 접근불가하다고 생각해서 에러를 낸 것이다
 
int main()
{
  unsigned char ucVal;
  K5 obj;
  obj.k =100;
  cout<<obj.k<<endl;
  obj.c =200;  //여기서 에러 접근권한이 그대로 private로 남아있음
  cout<<obj.c<<endl;
  while('q'!=ucVal)
  {  
    printf("input order: \n");
    cin>>ucVal;
    if('u'==ucVal)
    {
      obj.speedup();
    }
    if('d'==ucVal)
    {
      obj.speeddown();
    }
    continue;
  }
  return 0;
}
다음과 같이 상속시 상속받은 멤버들을 public으로 선언하면 에러가 나지 않는다
class K5: public car,audio //단 audio는 접근 권한이 그대로 private이다

*자식 클래스에서 부모클래스의 오버로딩된 함수 부르기
동일한 이름의 함수가 부모클래스에도 존재하면 인자에 상관없이  자식 클래스의 함수가 불리게 되어 있다
따라서 다음과 같이 부모클래스의 함수를 부르기 위해서는 부모클래스의 이름과 스코프연산자를 사용해서 불러줘야 한다 (단 부모클래스의 상속시 접근권한을 public으로 설정해 줘야 함)

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

class audio
{
  char * maker;
  
  public:
    int a;
    void test(float)
    {
      cout<<"audio test"<<endl;    
    }
      
};

class car
{
  
  public:
    void test(char)
    {
      
      cout<<"car test"<<endl;    
    }

};

class K5:public car,public audio  //모두 public으로 설정
{
    int k;

    public:
    void test(int )
    {
      
      cout<<"K5 test"<<endl;    
    }
      void speedup()
    {
};


int main()
{
  unsigned char ucVal;
  K5 obj;
  obj.audio::test(3);  
  
  return 0;
}
그 결과는 다음과 같이 audio test가 불린다

*객체를 포인트하는 객체 포인터

다음과 같이 객체를 포인트하는 객체 포인터를 선언해서 그 포인터에 자식객체의 주소를  넣어보자

int main()
{
  unsigned char ucVal;

  K5 * p;
  p = &obj;
  p->test(3);
  car * p2;
  p2 = &obj;
  p2 -> test(3);
  
    return 0;
}

위의 결과를 실행해 보면 다음과 같다

위의 결과에서 보듯이  객체 포인터를 만들고 그 포인터에 자식의 객체주소를 대입하면 컴파일러가 알아서
부모와 자식의 멤버함수를 부르는 것을 볼 수 있다 그 이유는 K5클래스가 car클래스를 상속받으므로 자식클래스로
구현된 객체가 안에 car클래스의 성질을 포함하고 있다고 생각 할 수 있다
*한 부모에게서 상속받는 두 자식 클래스

object클래스로 부터 상속받는 human클래스객체와 dog클래스객체를 만들되 생성자 호출시 부모클래스의
non default 생성자(인자있는 생성자)를 불러서 각각의 type을 출력하는 객체를 만들어 보자
또 부모 클래스의 포인트배열을 만들어서 상속받은 객체들의 주소를 대입하고 public으로 선언한 멤버변수를 출력해
보자
출력해 보면 주소로 대입한 자식객체들의 type이 출력됨을 볼 수 있다
 




그 이유는 우리가 man이나 dog1이라는 객체를 만들때 각각의 객체를 포인트하는 포인터를 만들려면 human* 이나
dog*형으로 포인터를 각각 만들어야 한다 하지만  object형 포인터를 선언하면 아래의 상속받은 모든 객체를 
포인터할 수 있다 
그러나 단점도 있다 object 포인터를 만들어 아래 상속받은 객체를 포인터하면 상속받은 객체의 멤버함수를 부를 수 없다 
실제적으로 부를 수 있는 방법이 있다 (virtual fn)
위와 같은 것을 자동type casting이라 한다

 

728x90