20140930 (C++ 함수 오버로딩, 평활화 최종)

149일차












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

C++

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






------- 오버로딩

함수의 반환값, 이름은 같은데 인자만 다른 것



예)

함수                        타입

int test(int );             int (*)(int);

int test(int, int);         int (*)(int, int);


-> C에서는 불가능 하지만 C++에서는 가능하다

     이것이 함수 오버로딩



함수                        타입

int test(int );             int (*)(int);            -> O

int test(int, int);         int (*)(int, int);      -> O

char test(int );          char (*)(int);         -> X

int test(char);           int (*)(char);         -> O


-> 3번째 같은 경우 반환값이 다르기 때문에 오버로딩이 불가능하다.

    함수 타입, 이름이 같으면 오버로딩이 된다.












------- 이전에 C와 asm을 함께 섞어 사용하였는데,

C++도 섞어 사용할 수 있다. 먼저 .asm 파일을 확인해야한다.



소스)

#include <iostream>


void swap(int *, int *);

void swap(float *, float *);

void test();


int main()

{

int iA = 100;

int iB = 200;

float fA = 100.1;

float fB = 200.2;


std::cout << "iA : " << iA << std::endl;

std::cout << "iB : " << iB << std::endl;


swap(&iA, &iB);


std::cout << "iA : " << iA << std::endl;

std::cout << "iB : " << iB << std::endl << std::endl;


std::cout << "fA : " << fA << std::endl;

std::cout << "fB : " << fB << std::endl;


swap(&fA, &fB);


std::cout << "fA : " << fA << std::endl;

std::cout << "fB : " << fB << std::endl;


test();


return 0;

}


void swap(int * a, int * b)

{

int temp;


temp = *a;

*a = *b;

*b = temp;

}


void swap(float * a, float * b)

{

float temp;


temp = *a;

*a = *b;

*b = temp;

}







위와 같이 컴파일 하고, asm 파일을 확인하면


- main.cpp

...

17 swap(&iA, &iB);

...

25 swap(&fA, &fB);

...

30 test();

...


- main.asm

; Line 17

lea edx, DWORD PTR _iB$[ebp]

push edx

lea eax, DWORD PTR _iA$[ebp]

push eax

call ?swap@@YAXPAH0@Z ; swap

add esp, 8

...

; Line 25

...

call ?swap@@YAXPAM0@Z ; swap

...

; Line 30

call ?test@@YAXXZ ; test


swap 함수와 test 함수의 이름이 이상하게 선언되어 있다.

보안코드와 디버깅 코드가 더 추가되어서 그렇다고 한다.


17 line의 swap과 25 line의 swap의 이름이 서로 다르다.

C++에서는 함수 오버로딩으로 같은 이름을 사용하지만,

결국 asm 에서 다른 이름을 사용한다.





------- C로 마지막에 호출한 test() 함수를 구현하는데,

main.cpp에서 구현한 swap() 함수를 사용하여 구현한다.


소스)

#include <stdio.h>


void test()

{

int iA = 50;

int iB = 25;


swap(&iA, &iB);


printf("iA = %d, iB = %d\n", iA, iB);

}




편의를 위해 ms cl을 사용한다.

cl /Fa test.c 이렇게 컴파일 후 asm파일을 확인




- main.cpp

...

PUBLIC _test

...

8 swap(&iA, &iB);

...


- main.asm

; Line 8

lea eax, DWORD PTR _iB$[ebp]

push eax

lea ecx, DWORD PTR _iA$[ebp]

push ecx

call _swap

add esp, 8



여기 test.c에서 test 함수 이름과 사용할 swap 함수의 이름이 main.cpp에서 함수의 이름이 다르다.

    C                    C++

_test        !=     ?test@@YAXXZ

_swap     !=     ?swap@@YAXPAH0@Z


이것을 통일 시켜줘야 서로 통용이 가능하다.

그렇게 하기 위해서 main.cpp 소스를 다음과 같이 수정한다.


소스)

- main.cpp

....

extern "C" void swap(int *, int *);

void swap(float *, float *);

extern "C" void test();

....



함수 선언부에서 외부 함수를 사용한다는 기호?를 선언해 주는데,

"C"를 붙였다. "C"는 C와 통용 가능한 함수 이름으로 선언해 준다는 뜻인 것 같다.


그리고 컴파일 하고 (cl /Fa main.cpp), .asm 파일을 확인해 본 결과...


- main.cpp

...

17 swap(&iA, &iB);

...

30 test();

...


- main.asm

...

; Line 17

lea edx, DWORD PTR _iB$[ebp]

push edx

lea eax, DWORD PTR _iA$[ebp]

push eax

call _swap

add esp, 8

...

; Line 30

call _test



이렇게 C와 통용이 가능한 이름으로 바뀌었다.



둘이 함께 .obj 파일을 합쳐 컴파일(cl main.obj test.obj) 후, 실행 결과.




이렇게 함께 사용하여 컴파일이 가능하다.












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

평활화

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


소스)

aaa.txt


관련 자료)

히스토그램을 이용한 화소 점 처리.pptx



- 다음과 같이 3단계를 통해 평활화가 이루어진다.




단계별 소스)


- 1단계

명암 값의 빈도 수를 계산해 입력 영상의 히스토그램 생성


ucpPixel = BMbuf + stpBFH->bfOffBits;

for(uiYcount = uiY; 0 < uiYcount; --uiYcount)

{

for(uiXcount = uiX; 0 < uiXcount; --uiXcount)

{

++uiRcnt[*(ucpPixel+2)];

++uiGcnt[*(ucpPixel+1)];

++uiBcnt[*ucpPixel];


SetPixel(MemDC, uiXcount-1, uiYcount-1,

RGB(*(ucpPixel+2), *(ucpPixel+1), *ucpPixel));

ucpPixel = ucpPixel + 3;

}

ucpPixel = ucpPixel + uiPad;

}



- 2단계

각 명암 값 x에서 0 ~ x까지의 누적 빈도 수(누적합)를 계산


uiXcount = 0;

uiRhisto[uiXcount] = uiRcnt[uiXcount];

uiGhisto[uiXcount] = uiGcnt[uiXcount];

uiBhisto[uiXcount] = uiBcnt[uiXcount];

for(uiXcount = 1; 256 > uiXcount; ++uiXcount)

{

uiRhisto[uiXcount] = (uiRhisto[uiXcount-1] + uiRcnt[uiXcount]);

uiGhisto[uiXcount] = (uiGhisto[uiXcount-1] + uiGcnt[uiXcount]);

uiBhisto[uiXcount] = (uiBhisto[uiXcount-1] + uiBcnt[uiXcount]);

}



- 3단계

2단계에서 구한 누적 빈도 수를 정규화(정규화 누적합, 공식 = 누적값 * 최대밝기 / 총픽셀수)


for(uiXcount = 0; 256 > uiXcount; ++uiXcount)

{

uiRhisto[uiXcount] = (uiRhisto[uiXcount] * 255) / (uiX*uiY);

uiGhisto[uiXcount] = (uiGhisto[uiXcount] * 255) / (uiX*uiY);

uiBhisto[uiXcount] = (uiBhisto[uiXcount] * 255) / (uiX*uiY);

}





결과)












설정

트랙백

댓글