5.static,virtual,friend

본장에서는 C++ 문법의 마지막 부분으로 static,virtual,프렌드에 대해서 설명합니다. static의 개념은 클래스에 내장된 함수를 단지 그함수만 사용할수 있도록 보장을 하는 것이며 가상함수는 상속받은 함수에 오버라이딩을 하는것이아니라 두 개의 함수를 분리하여 설정하는 의미입니다. 프렌드의 개념은 성격이 다른 두 개의 클래스를 함께 사용하는 형태를 의미합니다.

1.static

static라는 선언은 클래스내에 있는 함수를 바로 외부에서 호출할수 있도록 하는형입니다. 다음은 static를 사용한 예입니다.

class CString{

protected:

char buff[80];

public:

static int GetIntValue(char *data);

};

int CString::GetIntValue(char *data)

{

return atoi(data);

}

GetIntValue는 data로 넘겨준 인자의 값을 정수로 전환하여 리턴하는 함수입니다. 실제 이함수는 CString안에서도 사용할수 있지만 독자적으로 사용하여도 매우 편리한 함수입니다. 이럴 경우 외부에서 사용하고자 할 경우 형 앞에 static를 설정합니다. 이럴 경우 외부에서 바로 GetIntValue를 사용할수 있습니다.

다음은 위의 CString GetIntValue를 사용한 예입니다.

void main()

{

char temp[80];

int gab;

sprintf(temp,"12345");

gab=CString::GetIntValue(temp);

printf("%d",gab);

gets(temp);

}

위의 main함수에서 temp에 설정한 12345를 바로 정수값으로 넘겨 받기위해서 CString::GetIntValue함수를 그대로 호출하고 있습니다.

클래스 내에서 설정한 함수들중 외부에서 사용하여도 유용한 함수들일 경우 이형을 선언합니다.  static형은 virtual과 함께 하여 MFC에서 매우 많이 사용하는 형입니다. 이이유는 특정 클래스에서 특정함수들은 바로 호출을 하는 것이 편리할경우가 많기 때문입니다. 다음편에서 static의 사용례를 많이 보시게 될것입니다.

본예는 CpEx08에입니다. 출력결과는 그림 1과 같습니다.

(그림 1) CpEx08 출력 결과

2.virtual

virtual 는 상위클래스에서 사용하는함수와 자신이의 함수를 동시에 사용하기 위해서 설정하는 형입니다. 오버로딩 예제인 CpEx07에서 Draw를 CFrameWnd에서 오버로딩했기 때문에 상위 클래스인 CWnd의 Draw를 사용하지 못합니다. 상위 클래스이 Draw도 사용하고 자신의 클래스인 Draw도 사용하고자 한다면 virtual이라는 형을 함수앞에 설정하면 됩니다.

다음은 virtual를 사용한 예입니다.

class CWnd{

:

void Draw();

:

};

class CFrameWnd:public CWnd

{

:

virtual void Draw();

:

};

void CFrameWnd::Draw()

{

printf(프레임 윈도우 출력\n");

CWnd::Draw();//상속받은 CWnd의 Draw함수를 호출한다.

}

위의 예에서 보면 CFrameWnd 안에 Draw를 오버로딩하면서 virtual의 형을 설정하였습니다. 이렇게 virtual 형을 설정하게 되면 상위 클래스인 CWnd의 Draw또한 사용할수 있습니다. CFrameWnd::Draw()의 내용을 보면 먼저 printf로 자신의 윈도우 정보를 출력하고 상속받은 상위 클래스의 CWnd::Draw()함수를 호출하였습니다. 이렇게 호출을 하면 CWnd의 Draw가 CFrameWnd의 맴버 변수의 값을 이용하여 가동하게 됩니다.

MFC의 프로그램에서는 virtual 함수를 매우 많이 사용하고 있습니다. 보통 윈도우에서 클래스의 맴버 함수들은 메시지 처리를 수행하는 부분이 많습니다. 이부분에서 메시지에 따라 특정 부분을 수행하고 나머지 복잡한 부분을 상위 클래스로 넘기는경우가 많습니다. MFC프로그램을 배울 때 이부분에 대해서 많은 것을 배우시게 될것입니다.

CpEx09는 CpEx07에서 Draw함수를 virtual로 사용한 예입니다.

(프로그램 소스)

//CWnd.h

//Cwnd 와 CFrameWnd클래스 헤더

class CWnd{

protected:

int x;

int y;

int cx;

int cy;

int color;

public:

void SetColor(int c);

void SetPos(int x1,int y1,int x2,int y2);

void Draw();

};

class CFrameWnd:public CWnd

{

protected:

char manu[80];

public:

void SetMenu(char *data);

void PrintMenu();

virtual void Draw();

};

/////////////////////////////////////////////////////

//CWnd.cpp

#include <stdio.h>

#include <string.h>

#include "CWnd.h"

void CWnd::Draw()

{

printf("%d %d %d %d 에 %d 색으로 윈도우 그림\n",x,y,cx,cy,color);

}

void CWnd::SetPos(int x1, int y1, int x2, int y2)

{

x=x1;

y=y1;

cx=x2;

cy=y2;

}

void CWnd::SetColor(int c)

{

color=c;

}

void CFrameWnd::SetMenu(char *data)

{

strcpy(manu,data);

}

void CFrameWnd::PrintMenu()

{

printf("메뉴명:%s\n",manu);

}

void CFrameWnd::Draw()

{

printf("%d %d %d %d 에 %d 색으로 프레임 윈도우 출력\n",x,y,cx,cy,color);

CWnd::Draw();//상속받은 CWnd의 Draw함수를 호출한다.

}

///////////////////////////////////////////////////////////

#include <stdio.h>

#include "CWnd.h"

void main()

{

char temp[80];

int x,y,cx,cy,color;

CFrameWnd *pWnd= new CFrameWnd;

printf("프레임을 그릴 좌표:");

gets(temp);

sscanf(temp,"%d %d %d %d",&x,&y,&cx,&cy);

pWnd->SetPos(x,y,cx,cy);

printf("색번호:");

gets(temp);

sscanf(temp,"%d",&color);

pWnd->SetColor(color);

pWnd->Draw();

pWnd->SetMenu("프레임 메뉴");

pWnd->PrintMenu();

delete pWnd;

}

(그림 2)CpEx09 출력 결과

3.friend

friend란 간단하게 말해서 친구라는 의미입니다. 본편 앞에서사람이 자동차를 친구로 삼아서 멀리 갈수 있다는 말을 했습니다. friend란 자신과 연관이 없는 다른 클래스의 맴버를 자신의 것처럼 사용할수 있는 형태를 이야기 합니다. 예를 들어서 CDouble라는 소수를 컨트롤 하는 클래스가 다음과 같다고 합시다.

class CDouble{

protected:

int value;

public:

static int DoubletoInt(double gab);

};

int CDouble::DoubletoInt(double gab)

{

double data;

data=gab/10.;

data=data+0.5;

return (int)data;

}

CDouble클래스 안에 있는 DoubletoInt라는 함수는 소수를 정수로 바꾸는 함수입니다. 이함수와 함게 CInt라는 클래스가 다음과 같이 있다면

class CInt{

protected:

int value;

public:

void SetValue(double data);

void SetValue(int data);

:

int GetValue(){ return value;}

};

value에 값을 저장할 때 double값이 설정하는 SetValue라는 함수가 있습니다. 이함수는 double의 데이터를 int로 전환한다음 (반올림 하여) value값에 저장하는 기능이 되어야 합니다. 이함수에서 CInt는 CDouble클래스의  DoubletoInt 기능을 가진 함수를 하나 만들어야 합니다. 이렇게 만들어 double값을 int로 전환하고 이것을 value에 저장할수 있기 때문입니다. 여기에서 friend의  기능을 이용하여 CDoubletoInt안에 있는 DoubletoInt를 자신의 클래스에 삽입할수 있습니다.

다음은 CInt클래스에 DoubletoInt 함수를 프렌드로 이용한 예입니다.

class CInt{

protected:

int value;

public:

friend int CDouble::DoubletoInt(double gab);

void SetValue(double data);

int GetValue(){ return value;}

};

friend를 사용하여 int CDouble::DoubletoInt함수를 자신의 맴버 함수로 설정한 것입니다. friend는 MFC에서는 많이 사용하지 않습니다. friend의 의미란 계층적이고 구조적인 형태와는 걸맞지 않은 것이기 때문입니다. 그러나 어떤 기능이라는 것은 이해하고 넘어갈 필요가 있기에 설명합니다. CpEx10은 friend를 사용한 예제입니다.

#include <stdio.h>

class CDouble{

protected:

int value;

public:

static int DoubletoInt(double gab);

};

class CInt{

protected:

int value;

public:

friend int CDouble::DoubletoInt(double gab);

void SetValue(double data);

int GetValue(){ return value;}

};

void CInt::SetValue(double data)

{

value=CDouble::DoubletoInt(data);

}

int CDouble::DoubletoInt(double gab)

{

return (int)gab;

}

void main()

{

double data;

CInt m_int;

data=3.142;

m_int.SetValue(data);

printf("%d\n",m_int.GetValue());

}