-
20141014 (C++ class내에 const, friend, static, 시리얼 통신 winapi)부산IT학원/스마트컨트롤러 2014. 10. 14. 10:54
157일차
-----------
C++
-----------
------- const
예제를 통하여 class 내에 const의 기능을 더 확인한다.
예제1)
#include <iostream>
using namespace std;
class SoSimple
{
private:
int num;
public:
SoSimple(int n) : num(n)
{
}
SoSimple & AddNum(int n)
{
num = num + n;
return *this;
}
void ShowData() const
{
cout << "num : " << num << endl;
}
};
int main()
{
const SoSimple obj(7);
// obj.AddNum(20); // error!
obj.ShowData(); // ok!
return 0;
}
obj 객체가 const 로 선언되었기 때문에, AddNum 함수가 const 함수가 아니라서
호출 자체가 에러인 것이다.
예제2)
#include <iostream>
using namespace std;
class SoSimple
{
private:
int num;
public:
SoSimple(int n) : num(n)
{
}
SoSimple & AddNum(int n)
{
num = num + n;
return *this;
}
void SimpleFunc()
{
cout << "SimpleFunc: " << num << endl;
}
void SimpleFunc() const
{
cout << "const SimpleFunc: " << num << endl;
}
};
void YourFunc(const SoSimple & obj) // 인자를 const로 받음
{
obj.SimpleFunc();
}
int main()
{
SoSimple obj1(2);
const SoSimple obj2(7);
obj1.SimpleFunc();
obj2.SimpleFunc();
YourFunc(obj1);
YourFunc(obj2);
return 0;
}
결과
YourFunc(const SoSimple & obj) 함수의 인수 자체가 const로 받았기 때문에
그 안에서 호출되는 객체는 모두 const로 호출된다.
------- friend
class 내에 friend를 선언하면 선언된 class에 private 멤버에 접근이 가능하다.
예제)
#include <iostream>
#include <cstring>
using namespace std;
class Girl; // class도 선언만 가능
class Boy
{
private:
int height;
friend class Girl; // friend 선언 위치는 class 내에 어느 곳이든 가능
public:
Boy(int len) : height(len)
{
}
void ShowYourFriendInfo(Girl & frn); // class 내에서 선언만 해두고 정의는 더 밑에 있다
};
class Girl
{
private:
char phNum[20];
public:
Girl(char * num)
{
strcpy(phNum, num);
}
void ShowYourFriendInfo(Boy & frn); // class 내에서 선언만 해두고 정의는 더 밑에 있다
friend class Boy; // friend 선언 위치는 class 내에 어느 곳이든 가능
};
// 정의가 여기 있는 이유는 Boy class에서 Girl class의 정의가
// 어떤지 모르니 Boy class 내에서 Girl class 에 대한 언급을 할 수가 없기에
// 밑에 다 정의를 해둔 것이다
void Boy::ShowYourFriendInfo(Girl & frn)
{
cout << "Her phone number: " << frn.phNum << endl; // private 멤버에 접근 가능
}
void Girl::ShowYourFriendInfo(Boy & frn)
{
cout << "His height: " << frn.height << endl; // private 멤버에 접근 가능
}
int main()
{
Boy boy(170);
Girl girl("010-1234-5678");
boy.ShowYourFriendInfo(girl);
girl.ShowYourFriendInfo(boy);
return 0;
}
여기서 함수의 접근도 설정할 수 있는데
int main()
{
Boy boy(170);
Girl girl("010-1234-5678");
boy.ShowYourFriendInfo(girl);
girl.ShowYourFriendInfo(boy);
boy.height = 180; // error!
return 0;
}
boy.height = 180; 코드는 에러인데
class Boy
{
private:
int height;
friend class Girl; // friend 선언 위치는 class 내에 어느 곳이든 가능
friend int main(); // 이렇게 main을 추가함
public:
...
위와 같은 방식으로 main()을 추가하면 main도 boy의 friend가 되었기 때문에
에러가 아니게 된다.
------- static 멤버 변수, 함수
class 내 변수에 static 을 붙이면 그 클래스에 그 변수 한 개만 할당되어
그 클래스의 객체들은 그 한 변수를 공유하게 된다.
class smart
{
public:
static int iNum;
};
또 함수에 static을 붙였을 시,
내부 함수나 변수는 static인 함수와 변수만 사용 가능하다.
예제)
#include <iostream>
using namespace std;
class smart
{
public:
static int iNum;
int iNum2;
public:
static void test()
{
cout << "test()" << endl;
iNum = iNum + 1;
// iNum2 = 0; // error! static 변수가 아니라서 사용 못함
}
};
int smart::iNum = 100;
int main()
{
cout << smart::iNum << endl;
smart::test();
cout << smart::iNum << endl;
return 0;
}
한 가지 흥미로운 것은 객체를 생성하지 않았는데 사용 가능하다는 것이다!!!
-------------------------
시리얼 통신 winapi
-------------------------
------- 어제 작성했던 시리얼 통신 DOS 모드로 작성했던 소스를
그래픽 모드로 재작성 하였다.
DOS 모드 소스)
#include <windows.h>
#include <stdio.h>
DWORD WINAPI Thread_Read(LPVOID);
HANDLE hComm;
int main()
{
u_char caString[10] = "하이~";
//char buf;
DWORD dwWritten;
DCB sPState;
COMMTIMEOUTS cTime;
DWORD ThreadID;
HANDLE hThread;
hComm = CreateFile("COM8", GENERIC_READ | GENERIC_WRITE
, 0, NULL, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL, 0);
if(INVALID_HANDLE_VALUE == hComm)
{
printf("포트 열 수 없음\n");
return 0;
}
if(0 == SetupComm(hComm, 4096, 3096))
{
printf("버퍼 설정 에러\n");
CloseHandle(hComm);
return 0;
}
if(0 == PurgeComm(hComm, PURGE_TXABORT | PURGE_TXCLEAR))
{
printf("버퍼 초기화 에러\n");
CloseHandle(hComm);
return 0;
}
sPState.DCBlength = sizeof(sPState);
if(0 == GetCommState(hComm, &sPState))
{
printf("시리얼 상태 읽기 에러\n");
CloseHandle(hComm);
return 0;
}
sPState.BaudRate = CBR_38400;
sPState.ByteSize = 8;
sPState.Parity = EVENPARITY;
sPState.StopBits = ONESTOPBIT;
cTime.ReadIntervalTimeout = MAXDWORD; // 시간 설정, 블록킹 됐을시 기다리는 시간
cTime.ReadTotalTimeoutMultiplier = 0; // 0은 무한 대기
cTime.ReadTotalTimeoutConstant = 0;
cTime.WriteTotalTimeoutMultiplier = 0; // 0은 무한 대기
cTime.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &cTime);
if(0 == SetCommState(hComm, &sPState))
{
printf("시리얼 상태 설정 에러\n");
CloseHandle(hComm);
return 0;
}
hThread = CreateThread(NULL, 0, Thread_Read, NULL, 0, &ThreadID);
while(1)
{
caString[0] = getch();
if(0 == WriteFile(hComm, caString, 1, &dwWritten, 0))
{
printf("쓰기 에러\n");
}
else
{
printf("쓰기 성공\n");
}
}
CloseHandle(hComm);
return 0;
}
DWORD WINAPI Thread_Read(LPVOID NotUse)
{
char buf = 0;
DWORD dwRead;
while(1)
{
Sleep(100);
ReadFile(hComm, &buf, 1, &dwRead, NULL);
if(0 != dwRead)
{
printf("[%c] ", buf);
}
}
}
그래픽 모드 소스)
#include <windows.h>
#include "resource.h"
#define ID_EDIT 100
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
void OpenSPort();
DWORD WINAPI Thread_Read(LPVOID NotUse);
HINSTANCE g_hInst;
LPCTSTR lpszClass=TEXT("Serial");
HWND hMain;
int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance
,LPSTR lpszCmdParam,int nCmdShow)
{
HWND hWnd;
MSG Message;
WNDCLASS WndClass;
g_hInst=hInstance;
WndClass.cbClsExtra=0;
WndClass.cbWndExtra=0;
WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
WndClass.hInstance=hInstance;
WndClass.lpfnWndProc=WndProc;
WndClass.lpszClassName=lpszClass;
WndClass.lpszMenuName=MAKEINTRESOURCE(IDR_MENU1);
WndClass.style=CS_HREDRAW | CS_VREDRAW;
RegisterClass(&WndClass);
hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,(HMENU)NULL,hInstance,NULL);
ShowWindow(hWnd,nCmdShow);
while (GetMessage(&Message,NULL,0,0)) {
TranslateMessage(&Message);
DispatchMessage(&Message);
}
return (int)Message.wParam;
}
HANDLE hComm;
HANDLE hThread;
BOOL bPortOnOff;
HWND hEdit;
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
u_char caString[128] = "하이~";
DWORD dwWritten;
switch (iMessage)
{
case WM_CREATE:
hMain = hWnd;
hEdit = CreateWindow(TEXT("edit"), NULL, WS_CHILD | WS_VISIBLE
| WS_BORDER | ES_AUTOHSCROLL
, 10, 10, 100, 25, hWnd, (HMENU)ID_EDIT, g_hInst, NULL);
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_OPEN:
OpenSPort();
break;
case ID_CLOSE:
if(TRUE == bPortOnOff)
{
CloseHandle(hComm);
CloseHandle(hThread);
bPortOnOff = FALSE;
}
break;
case ID_EDIT:
switch(HIWORD(wParam))
{
}
break;
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
void OpenSPort()
{
static DCB sPState;
static COMMTIMEOUTS cTime;
DWORD ThreadID;
if(TRUE == bPortOnOff)
{
CloseHandle(hComm);
CloseHandle(hThread);
// return 0;
bPortOnOff = FALSE;
}
hComm = CreateFile(TEXT("COM8"), GENERIC_READ | GENERIC_WRITE
, 0, NULL, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL, 0);
if(INVALID_HANDLE_VALUE == hComm)
{
MessageBox(hMain, TEXT("포트 열 수 없음"), TEXT("알림"), MB_OK);
return ;
}
if(0 == SetupComm(hComm, 4096, 3096))
{
MessageBox(hMain, TEXT("버퍼 설정 에러"), TEXT("알림"), MB_OK);
CloseHandle(hComm);
return ;
}
if(0 == PurgeComm(hComm, PURGE_TXABORT | PURGE_TXCLEAR))
{
MessageBox(hMain, TEXT("버퍼 초기화 에러"), TEXT("알림"), MB_OK);
CloseHandle(hComm);
return ;
}
sPState.DCBlength = sizeof(sPState);
if(0 == GetCommState(hComm, &sPState))
{
MessageBox(hMain, TEXT("시리얼 상태 읽기 에러"), TEXT("알림"), MB_OK);
CloseHandle(hComm);
return ;
}
sPState.BaudRate = CBR_38400;
sPState.ByteSize = 8;
sPState.Parity = EVENPARITY;
sPState.StopBits = ONESTOPBIT;
cTime.ReadIntervalTimeout = MAXDWORD; // 시간 설정, 블록킹 됐을시 기다리는 시간
cTime.ReadTotalTimeoutMultiplier = 0; // 0은 무한 대기
cTime.ReadTotalTimeoutConstant = 0;
cTime.WriteTotalTimeoutMultiplier = 0; // 0은 무한 대기
cTime.WriteTotalTimeoutConstant = 0;
SetCommTimeouts(hComm, &cTime);
if(0 == SetCommState(hComm, &sPState))
{
MessageBox(hMain, TEXT("시리얼 상태 설정 에러"), TEXT("알림"), MB_OK);
CloseHandle(hComm);
return ;
}
hThread = CreateThread(NULL, 0, Thread_Read, NULL, 0, &ThreadID);
bPortOnOff = TRUE; // 포트 열기가 완료되었으므로 TRUE
}
DWORD WINAPI Thread_Read(LPVOID NotUse)
{
char tt;
static TCHAR buff[] = TEXT("0x00 ");
DWORD dwRead;
while(1)
{
Sleep(50);
ReadFile(hComm, &tt, 1, &dwRead, NULL);
wsprintf(buff, TEXT("0x%02X "), tt);
if(0 != dwRead)
{
SetWindowText(hEdit, buff);
}
}
}
'부산IT학원 > 스마트컨트롤러' 카테고리의 다른 글
20141027 (C++ 객체 초기화, 대입연산자, 배열 연산자, ARM ADS) (0) 2014.10.27 20141015 (C++ class 내에 const static, mutable, 상속, ) (0) 2014.10.15 20141013 (C++ 복사 생성자, 시리얼 통신 winapi) (0) 2014.10.13 20141010 (C++ this) (0) 2014.10.10 20141008 (C++ 맴버 이니셜라이저) (0) 2014.10.08