<c++>
다중상속
다중 상속은 두 개 이상의 부모 클래스를 동시에 상속하는 경우를 말한다.
class Tico : public car, _______ , _________, ________ ,,,,,,,,
{
}
===============================================================
(다중상속.... 지우고.....처음으로 돌아왔다.)
tico.h의 tico클래스 안에 state() 함수를 생성하였다. 이 함수는 일단 자신이 호출 되었다는
사실을 출력하고, 다음으로 car클래스 안에 정의 되어 있는 state()함수를 호출 한다.
//tico.h
class tico:public car
{
public:
void state() //car클래스의 state()함수를 호출 하는 함수
{
cout<<"tico::state() 출력"<<endl;
car::state();
}
void Set_Color();
tico()
:car("Tico", 1000, "대우")
{
Color=car::red;
Active=car::Stop;
Handle=car::Left;
Emer=car::Eon;
state(); //여기서 위에 있는 void state()를 호출한다.
}
그리고 car클래스 안의 state()함수만 public로 변경하였다.
//car.h
protected:
void Set_Color();
void Set_Active();
void Set_Handle();
void Set_Emer();
public:
void state();
<실행결과>
===============================================================
이번에는 main.h 에서 state()함수를 호출 하는데 한번은 객체 A를 이용해서, 한번은
tico포인터를 이용해서 호출 하였다.
이렇게 하면 car 클래스 소멸자 함수가 호출되어 출력된다.
int main()
9 {
10 tico A;
11 A.state();
12
13 tico *tp=&A;
14 tp->state();
15
16
17 return 0;
18 }
19
<실행결과>
tico::state() 출력
tico::state() 출력
------------------------------
차이름 : Tico
차 가격 : 1000
차 색상 : Black
차 제조사 : 대우
차 상태 : Backward
차 핸들상태 : Eoff
차 Emer상태 : Stop
10
============================================================
다음은 car 포인터를 또 추가해주었다. car클래스 안에 있는 state()함수가 호출 되므로
위에서의 소멸자와 중복되어 두번 출력된다.
int main()
{
tico A;
A.state();
tico *tp=&A;
tp->state();
car *cp=&A;
cp->state();
return 0;
}
<실행결과>
tico::state() 출력
tico::state() 출력
------------------------------
차이름 : Tico
차 가격 : 1000
차 색상 : Black
차 제조사 : 대우
차 상태 : Backward
차 핸들상태 : Eoff
차 Emer상태 : Stop
10
------------------------------
차이름 : Tico
차 가격 : 1000
차 색상 : Black
차 제조사 : 대우
차 상태 : Backward
차 핸들상태 : Eoff
차 Emer상태 : Stop
10
=======================================================
이번에는 나머지 부분을 주석 처리 한뒤 인덱스가 10개인 배열을 만들어 보았다.
실행하면, 위의 실행결과들이 총 10번 실행된다. (실행결과는 생략한다.)
tico A;
A.state();
// tico *tp=&A;
// tp->state();
// car *cp=&A;
// cp->state();
tico B[10];
========================================================
<이제부터 car 클래스에 대한 수업을 뒤로 하고 새로 시작한다.>
앞으로 CM님의 별다른 지시가 없는한 default로 public을 사용한다.
#include<iostream>
using namespace std;
class A
{
public:
A() //default 생성자 정의
{
cout<<"클래스 A생성"<<endl;
}
};
class B:public A //B는 A로부터 상속 받는다.
{
public:
B() //default 생성자 정의
{
cout<<"클래스 B생성"<<endl;
}
};
int main()
{
A objA; //A클래스의 객체 생성
B objB; //B클래스의 객체 생성
return 0;
}
=================================================
main()함수안에이렇게해주었다
int main()
{
A objA;
B objB;
A *AP; //A클래스의 포인터 선언
B *BP; //B클래스의 포인터 선언
AP=&objA; //포인터 초기화
BP=&objB; //포인터 초기화
//위에까지만 하면 에러가 안난다.
AP=&objB;
BA=&objA;
//여기서는 에러가 난다. 아래의 초기화에서 에러 나는 것이고 위의 초기화는 에러가 아니다
//그 이유는 부모 클래스는 자식 클래스를 참조 할 수 있지만, 자식 클래스는 부모 클래스를
//참조 할 수없기 때문이다.
return 0;
}
==============================================================
다음은 클래스 A와 클래스 B 임을 구별할 수 있는 test()함수를 두 클래스에 정의 하였다.
void test()
{
cout<<"A클래스입니당"<<endl;
}
------------------------------------------------------------------
void test()
{
cout<<"B클래스입니당"<<endl;
}
main()함수에서 아래와 같이 호출 하였다.
int main()
{
A objA;
B objB;
A *AP; //A클래스의 포인터 선언
B *BP; //B클래스의 포인터 선언
AP=&objA; //포인터 초기화
BP=&objB; //포인터 초기화
// AP=&objB;
// BA=&objA;
(*AP).test();
(*BP).test();
<실행결과>
클래스 A생성
클래스 A생성
클래스 B생성
A클래스입니당
B클래스입니당
========================================================
아까 AP=&objB; 이건 대입이 된다고 하였는데, 그럼 이 부분을 메인함수
에 추가하여 함수를 호출 해 보았다.
A objA;
B objB;
A *AP; //A클래스의 포인터 선언
B *BP; //B클래스의 포인터 선언
AP=&objA; //포인터 초기화
BP=&objB; //포인터 초기화
// AP=&objB;
// BA=&objA;
(*AP).test();
(*BP).test();
AP=&objB;
(*AP).test();
근데 실행결과를 보면 ...
클래스 A생성
클래스 A생성
클래스 B생성
A클래스입니당
B클래스입니당
A클래스입니당
B클래스의 객체 주소를 A에 대입하였는데 B클래스의 test함수가 호출 되지않고
A클래스의 test함수가 호출 되었다.
이런 현상을 방지하기 위해 등장한 키워드가 virture이다.
부모클래스에 정의된 test()함수 앞에 virtual을 붙여보면,
virtual void test()
13 {
14 cout<<"A클래스입니당"<<endl;
15 }
<실행결과>
클래스 A생성
클래스 A생성
클래스 B생성
A클래스입니당
B클래스입니당
B클래스입니당
==============================================================
이제 메인 함수의 내용을 모두 지우고 다시 시작한다.
아래와 같이 동적할당 해보았다. 컴파일 잘 된다. 그런데... 실행해보면
생성자가 호출 되지 않았음을 알 수 있다.
int main()
{
A *AP=(A*)malloc(sizeof(A));
free(AP);
return 0;
}
아래의 소스에서 malloc()함수 대신 new를 이용하여 동적할당 하였다.
int main()
{
// A *AP=(A*)malloc(sizeof(A));
A *P=new A;
delete P;
// free(AP);
return 0;
실행 해보면 생성자가 호출 되었음을 볼 수 있다
<실행결과>
클래스 A생성
=============================================================
A클래스에 소멸자가 호출 되었는지 확인 해보기 위해 소멸자를 출력하는
default 소멸자를 만들었다.
~A()
{
cout<<"A클래스 소멸"<<endl;
}
실행해보면 소멸자도 호출 되었음을 볼 수 있다.
<실행결과>
클래스 A생성
A클래스 소멸
다음은 요소가 10개인 배열을 동적할당하였다. 이렇게 하면 총 10번씩 생성자와
소멸자가 호출 된다.
// A *AP=(A*)malloc(sizeof(A));
// A *P=new A;
A *P= new A[10];
// delete P; //포인터의 동적할당 해제는 이렇게
delete []P; //배열의 동적할당 해제는 이렇게
// free(AP);
<실행결과>
클래스 A생성
클래스 A생성
클래스 A생성
클래스 A생성
클래스 A생성
클래스 A생성
클래스 A생성
클래스 A생성
클래스 A생성
클래스 A생성
A클래스 소멸
A클래스 소멸
A클래스 소멸
A클래스 소멸
A클래스 소멸
A클래스 소멸
A클래스 소멸
A클래스 소멸
A클래스 소멸
A클래스 소멸
=====================================================
참고 : 함수 포인터
기본적으로 함수를 그 함수의 이름으로 호출하지만 함수 자체를 포인터로 선언하여
그 함수의 주소값을 대입하고 호출하는 형식으로도 사용할 수 있다.
#include<iostream>
using namespace std;
void test()
{
cout<<"test"<<endl;
}
int main()
{
void (*fp)(); //함수포인터를 선언하고
fp=test; //그 함수 포인터가 test함수를 가리키게 한다.
fp(); //함수 포인터를 이용하여 test함수를 호출한다.
return 0;
}
<API>
<스톡오브젝트>
|
==========================================================================================
<색상>
- 브러시를 변경하여 채워지는 면의 색을 바꾸기.
(WndProc함수 외에 다른 부분은 생략할 부분이 없으므로 생략하였음)
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH MyBrush, OldBrush; //브러시핸들을 저장할 변수 두개 선언
//MyBrush는 그리기에 사용할 브러시핸들
//OldBrush는 원래의 브러시를 잠시 저장하는 브러시 핸들. SelectObject
//함수가 리턴 하는 값이 기존의 핸들 값인데 이 변수에 저장해 놓는다.(복구용)
switch (iMessage)
{
case WM_PAINT:
hdc=BeginPaint(hWnd, &ps);
MyBrush=(HBRUSH)GetStockObject(GRAY_BRUSH); //GetStockObject함수
//로 회색의 브러시 핸들을 얻되 대입을 위해 캐스팅하였다.
OldBrush=(HBRUSH)SelectObject(hdc, MyBrush); //구한 브러시를 사용
//하기 위해 GDI오브젝트를 DC에 선택하는데 쓰이는 함수
Rectangle(hdc,50, 50, 300, 200);
SelectObject(hdc, OldBrush); //원래의 GDI오브젝트로 돌아온다.
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
===================================================================================
배경화면을 검정색으로 하고, 브러시는 회색, 펜을 흰색으로 지정해 보았다.
우선 WinMain에서 아래의 이부분만 이렇게 살짝 바꿔 준다.
WndClass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH);
그다음 WinProc을 아래와 같이 편집...
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam, LPARAM lParam) |
=========================================================================
<펜>
위에서 펜을 흰색으로 지정하였다.. 문제 없었다.. 윈도우가 기본으로 제공하는 스톡 펜에
흰색이 있었기 때문에 문제가 없었던 것이다(흰색, 검정색, 투명색 세가지 뿐이다.)
그 외의 색들을 사용하기 위해서는 직접 만들어서 써야 한다.
다음은 CreatePen()함수를 이용하여 펜의 색을 변경한 것이다.
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam, LPARAM lParam) |
펜의 색이 파란색이 되었음을 볼 수 있다.
==========================================================================
<브러시>
브러시는 채워지는 면을 채색하는 용도로 사용된다.
브러시를 만드는 함수에는 두가지가 있는데,
CreateSolidBrush() 는 브러시의 색상만을 인수로 전달하고,
CreateAatchbrush() 는 생상과 함께 무늬도 지정할 수 있다.
아래의 소스는 파란색의 굵은 펜과 분홍색의 줄무늬를 가지는 사각형을 나타내는 소스이다.
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam, LPARAM lParam) |
================================================================================
<투명 오브젝트>
스톡 오브젝트 도표에서 브러시와 펜은 투명색의 NULL_BRUSH와 NULL_PEN이라는 것이 있는
데 이 오브젝트는 그리기를 하지 않는 오브젝트라는 뜻이다.
위의 그림처럼 Pen이나 Brush중 하나만 그리고 싶을 때는 그리고 싶지 않은 부분에 투명 오브젝트(NULL_????) 를 선택해 놓고 그려야 한다. <과제> 위의 그림에서 아래쪽에 사각형의 투명 오브젝트를 하나 추가하기. 펜은 NULL로 브러시는 녹색으로 그리고 세로로 줄 긋기
|
<그리기 모드>
|
SetROP2함수 호출 문을 주석처리 하고 다시 실행하면 이러한 그림이 나타난다.
한번 출력한 선을 지우지 못하기 때문에 마우스가 움직이는 족족 새로운 선이 그려지는
것이다. 이동중에 계속 선의 모양을 보여주기 위해 그리기 모드라는 것이 반드시 필요하다.
'코스웨어 > 10년 시스템제어' 카테고리의 다른 글
[시스템 제어]5월 18일 6번 김 신 호 (0) | 2010.05.19 |
---|---|
WinVi 편집기(윈도우에서 사용가능한 vi편집기) 및 몇가지 자주사용하는 명령어. (3) | 2010.05.19 |
시스템 제어 일일 보고서 - 8조 김민철(4번) (1) | 2010.05.18 |
시스템제어 - 헥사뷰어 실습 파일입니다. (0) | 2010.05.18 |
2010. 05. 13 김동수(2번) (2) | 2010.05.13 |
[시스템제어] 5월 12일 수 (30번 한정희) (1) | 2010.05.13 |
일일보고 순서 ((( 수정 ))) (1) | 2010.05.12 |
시스템제어(10/05/10) - C++(참조전달, 생성자, 소멸자), WinAPI(TextOut, GraphOut, MessageBox) (1) | 2010.05.10 |