C++ - car class 추가, 다중상속, 유도(derivation), 타입
※ HUD(Head Up Display)
→ 유리 등에 화면이 출력되는 것.
→ 처음 비행기에 적용되었고, BMW의 상위 차량 등에 소수 사용되고 있는 것을 확인할 수 있다.
- car class에 오디오 속성 적용
→ 자바는 객체를 물려 받는 걸 하나로 제한한다.(단일 상속)
→ C++은 객체를 물려 받는 것을 여러개 허용(다중 상속)
→ 생성 순서(어느 객체가 먼저 생성되고 소멸되는지) 등을 명확히 확인해서 에러 해결에 이용한다.( → 프로그램을 짤 때 원인을 알아야만 한다.)
→ C++은 다중 상속을 지원한다.(class K5: car, audio)
→ derivation (유도, 도출, 미분...) 여기서는 유도의 뜻을 가지며 상속을 유도라 한다.
→ composition(구성)
→ 유도(부모 A, 자식 C), C가 A로 부터 상속 받았다.(유도 되었다.)
→ 예제
#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가 상속 받아야 사용할 수 있다.
→ 함수 오버로딩
#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<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 = 0; 2>iCnt ; ++iCnt)
{
cout << array[iCnt]->type << endl;
}
return 0;
}
→ object *를 선언하므로써 Human* 타입과, Dog* 타입을 각각 따로 만들 필요 없이 사용할 수 있다.
→ 부모 클래스인 object *는 두 타입을 모두 포함하므로 따라서 각각의 클래스가 많아져 타입이 늘어나더라도 object *로 묶어서 사용할 수 있다.
for(int iCnt = 0; 2>iCnt ; ++iCnt)
{
cout << array[iCnt]->type << endl;
}
→ 실행 결과
→ 즉, 위와 같이 서로 다른 두 타입을 object *로 묶어서 배열로 선언하고 for문을 이용하여 출력하였다.
→ 이 방법을 사용하면 다양한 타입을 통일하여 사용할 수 있으므로 타입이 많을 경우 매우 유리하다.
→ 자바는 모조리 상속 받아서 최상위 객체가 존재하고 이것이 object 객체이며 void *와 같다.
→ mfc 등도 object 클래스를 가지나 예외가 존재하며 C++은 C를 포함하기 위해 조금 더 복잡한 구조를 가져 object 객체가 없으나 void *를 직접 쓸 수 있다.
'내장형 하드웨어 > C++' 카테고리의 다른 글
C++ 배열 포인터 복습 (0) | 2011.11.16 |
---|---|
C++ - 객체 소멸 순서, 객체 생성(정적, 동적 할당-malloc, new) (0) | 2011.11.15 |
C++ 생성자, 소멸자, 상속 (0) | 2011.11.11 |
C++ 클래스, 접근속성, scope 연산자(::), inline (0) | 2011.11.10 |
C++ (함수 인자의 새로운 용법, 오버로딩 과정 확인) (0) | 2011.11.09 |