Post

const : 변수가 상수가 되도록 정의하는 키워드


* 함수의 인자에 const 키워드를 선언한다면 구현 부분에도 const를 추가한다

선언부

void PrintNumber(const int nValue);


구현부

void PrintNumber(const int nValue)

{

printf("%d \n", nValue);

}


* 멤버변수의 값이 멤버함수 내에서 변경되지 않도록 만들려면 함수 선언 맨 뒤에 const를 추가한다.

(지역변수는 const 함수 내에서도 값 변경이 된다)


선언부

class Level

{

int nLevel = 0;

public:

// 함수안에서 값을 변경할 수 없을 때

void SetLevel(int nValue) const;

};


구현부

void Level::SetLevel(int nValue) const

{

int temp = nValue;

//nLevel = nValue;


* const 키워드를 포인터 변수에 사용할 시 위치에 따라 의미가 달라진다.


const int* p = &a;

const가 맨 앞에 있는 경우 : 포인터가 가르키는 변수의 값을 변경시키지 못한다.

*p = 22;   (X)



int* const p = &a;

p = &b;   (X)
const가 포인터* 뒤에 있는 경우 : 포인터가 가르키는 주소를 변경하지 못한다. 

 

Post

C3083 왼쪽의 기호는 형식이어야 합니다 에러


아무리 선언되어있는 헤더파일을 INCLUDE해도 'INFO 왼쪽의 기호는 형식이어야 합니다' 에러가 떴다..

찾아보니..... 전방선언에 가려져있었다....


예를들어 namespace PC::INFO::SKILL 클래스를 사용하려고 했다면...

아래처럼 PC namespace가 먼저 전방선언되어있었다...


Attack.h


namespace PC{

class LevelInfo;

}


class Attacak

{

typedef PC::INFO::SKILL SKILL_INFO

}


Skill class를 전방선언하면 해결

사실 PC::INFO::SKILL::SKILL_TYPE 이란 enum을 전방선언으로 가져와쓰고 싶었는데 안된다!!!

namespace PC

{

namepsace INFO

{

class SKILL;

struct SKILL::SKILL_TYPE;

}

}


이렇게 정방선언하고 SKILL_TYPE::ENUM쓰면 .......ENUM 정보가 없으므로 가져오지 못한다...

Post

예시로 임의로 작성한 소스코드

< Close.h >
namespace Game
{
namespace Player
{
class GradeInfo;
}
}

namesapce War
{
class Close
{
    typedef Game::Player::GradeInfo GRADE_INFO;
    GRADE_INFO* GetCloseGradeInfo(PC* pc);
}
}

< Close.cpp >
include "../../../Game/Player/GradeInfo.h"
namesapce War
{
GRADE_INFO GetCloseGradeInfo(PC* pc) //<<<<식별자 GRADE_INFO가 정의되어 있지 않습니다. 에러
{

}
}

문제 : Close 헤더파일에서 typedef로 GRADE_INFO를 선언했는데도
GRADE_INFO 정의를 찾지 못했다.
내가 Close 클래스내에서 typedef를 사용했으니
리턴값은 GRADE가 아닌 Close::GRADE_INFO이다.

Post

프로토콜이란? 두 컴퓨터가 통신을 위해 정한 규약.
프로토콜의 3가지 요소
구문 : 데이터 구조나 포맷 ( 앞에서부터 4비트까지는 주소.. 그 후 8비트는 데이터.. 이런식으로 어떤정보를 포함하는지)
의미 : 전송되는 데이터의 각 부분이 무엇을 뜻하는지 알 수 있게 미리 정해둔 규칙 ( 앞에서 부터 4비트가 1111일 때 어떤의미인지)
순서

프로토콜의 기능
종류별로 제공하는 기능이 다르지만, 공통적으로 다음과 같은 것을 제공
주소설정, 순서제어, 데이터 대열의 단편화 및 재조합, 캡슐화 등등..

SSL Protocol ? 서버와 클라이언트가 보안을 위해 사용하느 프로토콜.
ICMP Protocol ? 인터넷 제어 메시지 프로토콜.
QUIC Protocol ? 크롬이 사용하는 프로토콜.



Route

내 Pc Route 확인

cmd창에서 rount PRINT

활설경로 (NetworkDestination)이 0.0.0.0일 경우 

라우팅 테이블에서 직접 구체적으로 지정한 주소 외의 모든 목적지 주소는 인터페이스를 통해 게이트웨이 주소로 보내라는 의미.


Route 라인 동작 실험

cmd창에서 tracert 200.200.200.200 ICMP 프로토콜로 패킷 전송



Post

C3867 비표준 구문입니다. &를 사용하여 멤버 포인터를 만드세요

함수 호출하는데 () 괄호를 안넣음.

괄호넣으니 해결

Post

C++ 람다식이란?


람다는 익명함수로 크게 Capture(캡쳐), Parameter(인자), Return(리턴), Body(몸체) 로 나눌 수 있다.

아무것도 안하는 람다함수는

[] () {};

로 표현할 수 있다.


[Capture] (Parameter) {Body}


1. Capture

Capture는 람다 함수 밖에 있는 변수를 가져와 사용하고 싶을 때 사용한다.

예를들어 선언되어있는 지역변수 a를 출력하고 싶다면 이렇게 한다.


[int a](){ cout << a << endl; };


괄호안에 =, & 이 들어갈 수 있는데

= 는 모든 지역변수를 값으로 사용하겠다는 뜻이고

&는 모든 지역변수를 레퍼런스로 사용하겠다는 뜻이다.


2. Parameter

람다 함수 안에서 사용할 인자를 선언한다.

만약 지역변수와 이름이 같다면 에러를 나타낸다.

그리고 생략할 수도 있다.





명시적으로 3을 출력하고 싶다면


[](){cout<<3<<endl;}();


뒤에 ();를 붙여서 쓰면 호출이 된다.

어떤 함수에 저장해서 사용하고 싶다면 


auto func = [](){cout<<3<<endl;};

func()


();를 빼야 한다.



이것말고 더 어려운 부분도 있었는데 계속 정리해야겠다.




Post

IOCP 소켓 종료 상황


소켓이 CloseSocket으로 안전하게 끊어졌는지, 아닌지에 따라

정상종료. 비정상종료로 나눌 수 있다.


정상종료는 GetQueuedCompletionStatus 완료된 바이트 수가 0일 때..


비정상 종료는 GetQueuedCompletionStatus 함수의 리턴값이 0이고 WSAGetLastError값이 64 이다.

그리고 IO도 NULL이 아니다.


나는 이렇게 사용하였다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    
            int err = WSAGetLastError();
            if(NULL == userInfo)
            {
                PrintColor(YELLOW, "userInfo는 NULL! h \n");
            }
            else if((!result && WSAGetLastError() == 64)&& ioInfo != NULL// 비정상 종료
            {
                printf("bytesTrans가 0이라 종료합니다 ID:%d \n", userInfo->id);
                closesocket(sock);
                int id = userInfo->id;
                EnterCriticalSection(&cs);
                UserList.RemoveKey(userInfo->id);
                SAFE_DELETE(userInfo);
                SAFE_DELETE(ioInfo);
                LeaveCriticalSection(&cs);
        
                printf("접속자 %d가 나갔습니다. \n", id);
                PrintColor(YELLOW, "접속자 나갔습니다. \n");
                continue;
            }
            else if(!bytesTrans)
            {
                PrintColor(YELLOW, "정상적인 종료! \n");
            }
cs


Post

1. #include <crtdbg.h>를 한다.

2. 소스 코드 처음에 _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); 을 추가한다.

3. 만약 누수가 있다면


Detected memory leaks!
Dumping objects ->
{62} normal block at 0x00C34C50, 24 bytes long.
 Data: <                > 03 00 18 00 00 00 00 00 00 00 00 00 00 00 00 00 
Object dump complete.


이런식으로 나온다.


그리고 A부모 클래스가 있고 B자식 클래스가 있을 때

A* pB = new B()했을 경우

delete(pB)를 해도 메모리 누수가 되지 않는다.


Post

옛날부터 다중상속을 하면 어떻게 되는지 헷갈렸다.

그래서 A, B를 동시에 상속받은 C가 Func를 호출하게 했다.

Func함수는 A, B 클래스에 동시에 있으므로

결론은 error C2385: 'Func' 액세스가 모호합니다.' 가 뜬다.

호출하려면 어떤 클래스인지 명확하게 지정해주고 사용한다.

그러므로 C클래스 안에서 Print 함수를 만들어서 부모를 지정해준 뒤 함수를 호출하면 된다.



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <stdio.h>
#include <windows.h>
 
class A
{
public:
    int a;
    int b;
    A()
    {
        a = 100;
        b = 101;
    }
    
    void Func()
    {
        printf("A입니다 \n");
    }
};
 
class B
{
    
public:
    int a;
    int b;
    B()
    {
        a = 200;
        b = 201;
    }
    void Func()
    {
        printf("B입니다 \n");
    }
};
 
class C : public A, public B
{
public:
 
};
 
void main()
{
    C c;
    printf("%d %b \n", c.a(), c.b);
    getchar();
}
cs


Post

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <stdio.h>
#include <windows.h>
#include <process.h>
 
#define NUM_THREAD 50
unsigned WINAPI threadInc(void* arg);
unsigned WINAPI threadDes(void* arg);
 
long long num = 0;
CRITICAL_SECTION cs;
 
int main(int argc, char* argv[])
{
    HANDLE tHandles[NUM_THREAD];
    int i = 0;
 
    InitializeCriticalSection(&cs);
    
    for(int j = 0; j < 2++j)
    {
        tHandles[i] = (HANDLE)_beginthreadex(NULL0, threadInc, NULL0NULL);
        ++i;
    }
    DWORD returnMessage = WaitForMultipleObjects(2, tHandles, TRUE, INFINITE);
    DeleteCriticalSection(&cs);
    printf("result:%d \n", num);
    return 0;
}
 
unsigned WINAPI threadInc(void* arg)
{
    int i;
    EnterCriticalSection(&cs);
    for(i = 0; i<1000++i)
    {
        num+=1;
        printf("num:%d i:%d \n", num, i); 
    }
    //LeaveCriticalSection(&cs);
    return 0;
}
 
unsigned WINAPI threadDes(void* arg)
{
    int i;
    EnterCriticalSection(&cs);
    for(i = 0; i<1000000++i)
        num-=1;
    //LeaveCriticalSection(&cs);
    return 0;
}
cs


윤성우의 TCP/IP책으로 공부를 하고 있다.

데드락에 대한 예제를 찾기가 어려웠다.

예전에는 데드락이 의도치 않게 잘 일어났었는데... 지금은 잘안됨 ㅋㅋ

일단 허접하게 LeaveCriticalSection을주석처리해서 다른 쓰레드가 접근하지 못하게 했다. 


내가 이해안가던게, 크리티컬 섹션에 접근을 못하는 건지, 해당 변수에 접근을 못해서

데드락이 걸리는건지 헷갈렸는데..

크리티컬 섹션을 꼼꼼히 안해주면 크리티컬 섹션 효과를 못보니까 크리티컬 섹션에 접근을 못해서 문제인 듯.



'이전게시판 > C, C++' 카테고리의 다른 글

C++ 11 람다식(Lamda)이란 - 1  (0) 2016.06.19
IOCP 소켓 종료 상황  (0) 2016.04.21
CRT 메모리 누수 체크  (0) 2016.04.15
C++ 다중상속 문제점?  (0) 2016.04.04
2의 보수 만드는 법  (0) 2016.04.01
구조체 패딩이란?  (0) 2016.03.31
C++ 스택(Stack) 예제  (0) 2016.03.20
C++ 간단한 원형 큐  (0) 2016.03.20
▲ top