20141013 (C++ 복사 생성자, 시리얼 통신 winapi)

156일차






-----------

C++

-----------



------- 복사 생성자

예제를 보자.


소스)

#include <iostream>

#include <cstring>


using namespace std;


class smart

{

public:

char * p;


public:

smart()

{

cout << "D생성자" << endl;

p = new char[3];

strcpy(p, "Hi");

}


smart(const smart & r) // 복사 생성자, 복사 받는 값은 변경하지 않으니

{ // 보통 앞에 const를 붙인다

p = new char[3];

strcpy(p, r.p);

cout << p << "복사 생성자" << endl;

}


~smart()

{

cout << "~소멸자" << endl;

delete []p;

}


smart test()

{

smart t;

*(t.p) = 'X';

return t;

}

};


int main()

{

smart obj1; // 디폴트 생성자 호출

smart obj2; // 디폴트 생성자 호출


// obj2 = obj1; // 대입 연산자 호출


*(obj2.p) = 'L';


smart obj3 = obj2; // 복사 생성자 호출

smart obj4(obj3); // 복사 생성자 호출


smart obj5 = obj4.test();


cout << "this is test" << endl;


return 0;

}


결과





위 처럼 생성자인데 바로 다른 값을 넣어주는 것을 복사 생성자라 한다.

이것을 선언해 주지 않을시 기본값으로 만들어져 있다.


만약 위 소스에서

smart(const smart & r) // 복사 생성자, 복사 받는 값은 변경하지 않으니

{ // 보통 앞에 const를 붙인다

// p = new char[3];

// strcpy(p, r.p);

cout << p << "복사 생성자" << endl;

}

해버리면 오류다ㅋ


http://wowcat.tistory.com/1946








------- explicit

복사 생성자를 사용할 때 묵시적 변환이 일어나서

복사 생성자가 호출되는 경우가 있는데, 무슨 말이냐 하면...


smart obj1 = obj2;      =>      smart obj1(obj2);


이렇게 묵시적으로 바뀐다.

여기서 smart obj1 = obj2; 형태가 맘에 들지 않으면 복사 생성자의 묵시적 호출을

허용하지 않을 수 있는데, 이때 사용하는 키워드가 explicit 이다.


예제)

class smart

{

public:

smart()

{

cout << "디폴트 생성자" << endl;

}

explicit smart(smart n)

{

cout << "복사 생성자" << endl;

}

};


int main()

{

smart obj1;


smart obj2(obj1);     // ok!

smart obj3 = obj1;    // error!


return 0;

}





------- 임시 객체

실제로 쓰지는 않고 임시 객체를 통해서

생성자와 소멸자가 사라지는 시간을 확인하는 소스이다.


예제)

#include <iostream>


using namespace std;


class Temporary

{

private:

int num;

public:

Temporary(int n) : num(n)

{

cout<<"create obj: "<<num<<endl;

}

~Temporary()

{

cout<<"destroy obj: "<<num<<endl;  

}

void ShowTempInfo()

{

cout<<"My num is "<<num<<endl;

}

};


int main(void)

{

Temporary(100);

cout<<"********** after make!"<<endl<<endl;


Temporary(200).ShowTempInfo();

cout<<"********** after make!"<<endl<<endl;


const Temporary &ref=Temporary(300);

cout<<"********** end of main!"<<endl<<endl;

return 0;

}


결과













---------------------

Winapi 시리얼 통신

---------------------



------- 시리얼 통신

소스를 짜기 앞서,


사용할 포트를 설정해 줘야한다. Virtual Serial Ports Driver라는 프로그램으로

8번과 9번을 연결해 놓았다.


하이퍼 터미널로 9번을 열었다면, 작성할 소스는 8번을 열어야 한다.


소스)

#include <windows.h>

#include <stdio.h>


int main()

{

u_char caString[10] = "하이~";

DWORD dwWritten;

DCB sPState;

HANDLE 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;


if(0 == SetCommState(hComm, &sPState))

{

printf("시리얼 상태 설정 에러\n");

CloseHandle(hComm);

return 0;

}


if(0 == ReadFile(hComm, caString, sizeof(caString), &dwWritten, 0))

//if(0 == WriteFile(hComm, caString, sizeof(caString), &dwWritten, 0))

{

printf("쓰기 에러\n");

}

else

{

// printf("쓰기 성공\n");

printf("읽기 성공\n");

printf("[%s]\n", caString);

}


CloseHandle(hComm);


return 0;

}







------- 스레드 + 시리얼 통신

소스)

#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);

}

}

}







설정

트랙백

댓글