ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 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);

    }

    }

    }









Designed by Tistory.