본문 바로가기
코스웨어/11년 내장형하드웨어

[내장형]박춘우_2011년 11월 9일 수요일 DailyReport

by 알 수 없는 사용자 2011. 11. 9.
728x90
반응형
<함수 인자의 초기값 설정>
C 언어와 다른 C++ 의 문법을 살펴 봅시다. 함수의 인자에 값을 할당하는 다음 예제를 살펴봅시다.
컴파일 할 때 리눅스는 g++ 명령어로 하시고 파일은 C 파일로 테스트 해보세요. 윈도우는 cl 명령어로 cmd 창에서 컴파일 하시고 파일은 cpp 파일로 테스트 하시면 됩니다.

#include <stdio.h>

void test(int A, int B=3)
{
	printf("A : %d\n", A);
	printf("B : %d\n", B);

	return ;
}

int main()
{
	test(1,2);
	test(1);

	return 0;
}

 


test 함수의 인자를 살펴보아요. 두 번째 인자에 C 문법과는 다른 인자에 값을 할당하지요. 실행을 해보면 알겠지만 에러는 발생하지 않습니다. C++ 의 문법입니다. main 함수에서 test 함수를 호출하는 부분을 자세히 살펴봅시다. 첫 번째는 test 함수에 1 과 2 를 인자값으로 호출하지요. 출력 결과는 A 는 1 이 B 는 2 가 출력됩니다. 두 번째 test 함수에서는 첫 번째 인자값으로 1 만 주고 호출합니다. 출력 결과는 A 는 1 이 B 는 3 이 출력됩니다.

결론적으로 함수의 인자값에 값을 설정해주면 함수 호출 시 인자값을 넣지 않아도 설정된 값으로 할당되는 것을 알 수 있지요. 

하지만 여기서 아주 중요한 사실을 알고 넘어가야 합니다. 인자값에 값을 할당하는 것은 항상 오른쪽에 있어야 한다는 것입니다. 무슨 말이냐~!! 다음 예제를 살펴보면서 진행하도록 하죠~! 

#include <stdio.h>

void test(int A=1, int B)
{
	printf("A : %d\n", A);
	printf("B : %d\n", B);

	return ;
}

int main()
{
	test(1,2);
	
	return 0;
}

[Linux]



[Windows]



이번에는 test 함수의 첫 번째(왼쪽) 인자인 A 에만 1 을 설정해둡니다. 그리고 main 함수에서 호출을 합니다. 그럼 A 는 1과 B 는 2 를 출력할 것이라는 예상 결과가 나옵니다. 하지만 컴파일을 해보면 좌절을 하게됩니다. 앞서 언급했듯이 인자값에 값을 설정해주는 방법은 오른쪽에 있지 않으면 안되는 것을 알 수 있습니다.
만약 test 함수에서 첫 번째 인자를 설정값으로 사용하고 두 번째 인자값만 넣는다고 한다면 다음과 같겠죠

test( , 2);

하지만 뭔가 이상하지 않나요? 첫 번째 인자에 아무것도 없는 그냥 봐도 에러일 것 같은 느낌이 팍팍 느껴지시죠~??

그렇다면 무조건 오른쪽에만 되느냐?? 그것은 또 아닙니다. 오른쪽 부터 설정을 해줘야하는 것이죠~ 다음 예제를 살펴보면 알 수 있습니다.

#include <stdio.h>

void test(int A = 2, int B = 3)
{
	printf("A : %d\n", A);
	printf("B : %d\n", B);

	return ;
}

int main()
{
	test(1,2);
	test(1);
	test();
	return 0;
}
   


이번에는 test 함수에 인자값 모두 값을 설정했습니다. 아무 이상없이 출력이 되지요 3 번째 test 함수를 호출하는 부분에 보면 인자값을 하나도 넣지 않고 호출합니다. 그래도 아무런 문제가 없이 설정된 값으로 출력을 해줍니다.


<오버로딩>
오버로딩에 대해 어셈블리까지 접근하여 살펴보도록 합시다~!! 오버로딩을 이용한 함수를 생성하도록 합시다. 다음 예제 처럼요!! cpp 파일로 작성하시고 리눅스는 g++로 윈도우는 cl 로 컴파일 하시면 됩니다.


#include <iostream.h>

void test(int A)
{
	cout << "A : " << A << endl;
	return ;
}

void test(int A, int B)
{
	cout << "A : " << A << endl;
	cout << "B : " << B << endl;
	return ;
}

void test(float A)
{
	cout << "A : " << A << endl;
	return ;
}

int main()
{
	test(1);
	test(2,3);
	test(1.2f);

	return 0;
}



정상적으로 잘 동작합니다. 여기서 이야기 하고 싶은 내용은 main 함수에서 test 함수를 3 번 호출합니다. 이 때 함수 이름에 주목을 해봅시다. test 라는 함수의 이름이 동일 합니다. 그렇다면 과연 어떻게 구분을 하는 것일까요?? 분명 여기 소스 코드에서는 구분할 수가 있습니다. 인자가 다른 함수 3 개를 눈으로 봐도 보이니까요. 하지만 컴퓨터는 기계어로 처리하기 때문에 이름이 같은 함수를 호출하게 되면 문제가 발생합니다. 기계어에는 변수명이라는 것 조차 존재하지 않지요. 단지 프로그램언어에서 사람이 이해하기 쉽게 만들기 위해 만들어 놓은 하나의 장치에 불과합니다. 오버로딩을 하는 함수에서 같은 함수 이름을 사용하여 호출하는 것 역시 하나의 장치라 볼 수 있습니다.
장치인지 아닌지 알 수 있는 방법은 기계어 코드를 살펴보는 것이죠. 기계어는 도통 알아먹기 힘드니 어셈블리를 살펴봐야 할 것입니다. 따라서 어셈블리를 살펴보기 위해서는 컴파일의 중간 과정의 파일들을 생성해야 합니다. 어셈블리 파일을 생성하는 방법은 다음과 같습니다.

리눅스
g++ --save-temps -o <실행파일> <cpp파일.cpp>

윈도우
cl /Fa <cpp파일.cpp>  

리눅스의 s 파일을 열어 봅시다. main 이 시작하는 부분을 찾아보면 다음과 같습니다.



test 함수를 3 번 호출합니다. 그러나 호출하는 부분을 뚫어지게 살펴봅시다. 뭔가 이상하지 않나요? 분명 test 라는 이름의 함수를 3 번 호출 했습니다. 하지만 어셈블리에서는 서로 다른 이름으로 함수를 호출하고 있습니다. test__Fi, test__Fii, test__Ff 서로 다른 함수를 호출하고 있습니다.

윈도우에서도 살펴볼까요? asm 파일을 열어서 확인해봅시다.



어떤가요? 이상한 이름으로 함수를 호출하지만 잘 살펴보면 역시나 서로 다른 이름으로 함수를 호출하고 있습니다.

이제 정리해봅시다. 리눅스나 윈도우나 어셈블리에서는 다른 함수들을 호출합니다. 이는 앞서 언급했듯이 프로그램 언어는 단지 기계어를 만들어내는 도구일 뿐입니다. 따라서 오버로딩은 기계어를 사람이 쉽게 만들어내기 위한 하나의 기법이라 할 수 있습니다. 하지만 실제로는 함수 이름은 다르게 만들어집니다. C++ 언어에서는 같은 이름의 함수를 호출하는 것 처럼 사용하지만 내부적으로는 함수를 각각 다른 이름을 사용합니다.  다름 이름을 사용하지만 인자에 따라 조금씩 달라집니다. 이렇게 하는 것을 명칭 부호화라고 합니다.

함수의 이름이 바뀐다면 문제점이 발생할 수 있습니다.  만약 위의 함수와 같은 것을 라이브러리로 만들어졌다면 다른 파일에서 호출하여 사용하게 됩니다. 이 때 외부 파일에서 함수 이름을 사용할 때 함수의 이름이 변경된다면 링크 중에 에러가 발생할 수 있습니다. 이를 방지하기 위한 방법으로 함수 앞에 extern "C" 를 사용해 줍니다. 다음 예제를 살펴봅시다.




첫 번째 함수를 살펴보면 extern "C" 를 이용하여 함수를 생성하고 있습니다. 이 test 함수는 어셈블리에서도 이름이 변하지 않습니다. 못 믿겠다구요?? 컴파일 중간 파일을 살펴보아요~!!



첫 번째 호출하는 함수는 test 그대로 사용하고 있음을 확인 할 수 있습니다. 윈도우도 확인 해볼까요?



윈도우에서도 역시 _test 이름 그래도 함수를 호출합니다. _ 기호가 들어갔다고 다르다라고 하시면 안됩니다~ !!!!!!! 윈도우 어셈블리에서 함수를 표현할 때 사용하는 기호라는 사실을 알고 계신다면 말이죠 !!
여기서 한번 생각을 해봅시다. 함수 이름을 바꾸지 못하게 할 수 있다면 위의 남은 함수 2개도 extern "C" 를 사용하면 어떻게 될까요? 함수 이름이 똑같다. 똑같다.. 똑같다... 어떻게 구분하죠?? 문제가 생길 것 같죠?? 과연 어떻게 되는지 소스 코드를 수정해 봅시다. 다음과 같이 변경해서 컴파일 해보자구요 !!

#include <iostream.h>

// 오버로딩한 함수 이름이 동일함
extern "C" void test(int A)
{
	cout << "A : " << A << endl;
	return ;
}

extern "C" void test(int A, int B)
{
	cout << "A : " << A << endl;
	cout << "B : " << B << endl;
	return ;
}

extern "C" void test(float A)
{
	cout << "A : " << A << endl;
	return ;
}

int main()
{
	test(1);
	test(2,3);
	test(1.2f);

	return 0;
}

[Linux]


[Windows]


예상했던 결과가 나타나는군요 같은 이름을 사용하지 못하기 때문에 문제가 발생합니다. 이러한 문제 말고 다른 문제도 한번 알아 볼까요?? 다음 예제를 살펴봅시다.

#include <iostream.h>

void test(double A)
{
	cout << "A : " << A << endl;
	return ;
}

void test(long A)
{
	cout << "A : " << A << endl;
	return ;
}

int main()
{
	test(1);
	test(2);

	return 0;
}

[Linux]


[Windows]


함수의 인자의 개수가 같은 경우는 문제가 발생합니다. 왜냐하면 main 함수에서 인자값으로 넣어줄 때의 값이 정수형 값이므로 test 함수에는 정수형 인자로 선언된 함수는 존재하지 않으므로 어떤 함수를 호출해야 하는지 모호해지기 때문이죠. 따라서 인자 값을 넣어 줄 때 정확한 타입을 넣어줘야 합니다. 다음과 같이 main 함수를 수정해 보아요.

int main()
{
	test(1.0);
	test(2l);

	test((double)1);
	test((long)2);

	return 0;
}



코스에 보면 2가지 방법이 있습니다. 해당 타입에 맞게 인자값을 넣어주는 방법과 강제형 변환을 이용하는 방법이죠. 이러한 모호성은 다음과 같은 코드에서도 살펴볼 수 있답니다.

#include <iostream.h>

void test(char A)
{
	cout << "A : " << A << endl;
	return ;
}

void test(int A)
{
	cout << "A : " << A << endl;
	return ;
}

int main()
{
	test('A');
	test(65);

	return 0;
}



main 함수에서 test 함수를 호출하는 것을 살펴보면 'A' 는 65 의 정수형 일까요 char 형 일까요? 모호하지 않나요? 그러나 컴파일을 해서 실행을 하면 문제는 없습니다. 이러한 모호한 경우는 되도록 피하는 것이 좋을 듯 싶습니다. 하지만 여기에서 제 생각으로는 기본적으로 상수는 정수형 취급을 합니다. 따라서 65 로 직접적으로 인자를 넣어주면 정수형의 함수로 'A' 를 넣어 주면 아스키 코드로 간주하여 char 형으로 출력하는 것 같네요.

더 재밌는 사실은 위의 test 함수 중 char 형 인자를 받는 함수를 주석 처리해서 컴파일을 하면 결과는 다음과 같이 나옵니다.



'A' 를 인자로 넣은 test 함수는 정수형으로 취급해 버립니다. 또한 반대로 정수형 인자를 받는 test 함수를 주석 처리하고 컴파일 후 출력하면 다음과 같이 나옵니다.



65 를 인자로 넣은 test 함수는 char 형으로 취급해 버립니다. 모호한 상황이 많이 발생하는군요. 이렇게 모호한 상황을 되도록이면 만들지 않도록 해야할 것 같습니다~!


<강 자료형>
강 자료형이란 C 언어는 자료형이 다르더라도 어느정도는 허용해 줍니다. 하지만 C++ 에서는 자료형이 다르다면 에러를 발생시키거나 최소 경고를 띄워줍니다. 객체지향 언어는 대부분 자료형에 대해서는 강력하게 대처합니다. 우리들은 관대하나 C++, JAVA 와 같은 객체지향 언어는 자료형에 대해서는 엄격합니다. 자료형을 강력하게 사용한다는 의미가 되겠습니다.

다음 예제를 살펴봅시다. 다음 예제는 c 파일과 cpp 파일 모두 만들어 컴파일 해봅시다.

#include <stdio.h>

int main()
{
	int a = 100;
	int *b = &a;
	void *v;
	
	v = b;
	b = v;
	
	printf("b : %d\n", *b);

	return 0;
}

C 언어 컴파일 결과



C++ 언어 컴파일 결과
[Linux]


[Windows]


C 언어로 컴파일하여 출력을 했을 때는 아무런 이상이 없이 정상 작동합니다. 소스 코드를 살펴보면 분명 void * 형의 v 와 int * 형의 b 와 서로 값을 할당합니다. 분명 다른 자료형인데 말이죠. 하지만 C 언어는 허용해 줍니다.
하지만 C++ 언어는 자비란 없습니다. 바로 에러를 출력해 줍니다. 자료형에는 완전 엄격합니다. 따라서 올바르게 고치기 위해서는 강제형 변환을 해야합니다. 다음과 같이 말이죠~!!!!

v = (void *)b;
b = (int *)v;

위의 코드로 수정한 후 출력을 하면 C 언어로 작성한 코드와 같은 결과를 볼 수 있습니다.

결론적으로는 C++ 언어를 사용하는 데 있어서 자료형에 대해서 꼼꼼하게 따져가며 코드를 작성해야 합니다. C++ 언어 뿐만 아닌 객체지향 언어는 대부분 그렇습니다.



<전역 변수의 동적 초기화>
C 언어에서 전역 변수와 static 변수는 컴파일 할 때 생성되어 초기화 되는 정적 변수입니다. 반면에 지역 변수는 런타임 때 함수에 의해 생성되고 사라지는 동적 변수입니다.
하지만 C++ 언어에서는 전역 변수를 동적 변수로 만들 수 있습니다.  도대체 무슨말이냐??  그렇다면 예제를 먼저 살펴봅시다 !!  C 파일과 C++ 파일 두 파일을 생성하여 컴파일 해봅시다.

#include <stdio.h>

int test()
{
	int iNum;
	
	printf("숫자를 입력하세요\n");
	scanf("%d", &iNum);
	
	return iNum;
}
// 동적 초기화 
int a = test();

int main()
{
	int iA[5] = {0, 1, 2, 3, 4};
	
	printf("a : %d\n", a);
	printf("iA[4] : %d\n", iA[4]);
	printf("iA[4] : %d\n", *(iA+4));
	printf("iA[4] : %d\n", *(4+iA));
	printf("iA[4] : %d\n", 4[iA]);
	
	return 0;
}

C 언어의 컴파일 결과
[Linux]


[Windows]


C++ 언어의 컴파일 결과


C 언어에서는 전역 변수는 정적 초기화만 가능하므로 컴파일 에러를 보여줍니다. 하지만 C++ 언어에서는 아무런 이상이 없습니다. 전역 변수 a 는 test 함수의 리턴값을 할당 받아 출력합니다. test 함수는 사용자에게 정수형을 입력 받은 값을 리턴하구요. 결론은 test 함수가 동작하지 않으면 전역 변수 a 는 값을 초기화 할 수 없습니다. test 함수가 동작하려면 컴파일 단계에서 가능할까요? 불가능하지요. 런타임 때 함수가 호출됩니다. 따라서 전역 변수가 동적으로 초기화 되는셈이죠. 

여기에서 한번 더 깊게 생각해봅시다~!! C 언어에서 main 함수는 엔트리 포인트가 되는 프로그램의 시작 지점입니다. 즉 무조건 main 함수를 제일 먼저 호출하게 되지요. 하지만 위의 소스 코드를 살펴보면 이상한 점을 느낄 수 있습니다. 어디에도 main 함수에서는 test 함수를 호출하고 있지 않습니다. 다만 전역 변수 a 가 호출하여 리턴값을 할당받지요. 결국은 main 함수 보다 전역 변수를 초기화 하기 위해 test 함수가 먼저 호출되는 것을 유추할 수 있습니다.  그럼 문제가 발생해야 하는 것이 아니냐 !!!

하지만 C++ 은 그렇지 않습니다. main 함수의 엔트리 포인트 아닌 것이냐 !! 이 것 역시 아닙니다. 변하는 것이 아닙니다. 단지 우선순위가 밀어졌다는 사실입니다.

이 개념이 왜 중요하냐??? 그것은 바로 우리가 코드를 작성하는 데  이 사실을 몰랐다면 전역 변수를 초기화를 하다가 프로그램이 멈추는 버그가 발생했을 때를 생각해봅시다. 절대 main 함수는 동작하지 않겠죠. 하지만 main 함수 내에서 문제를 찾게 됩니다. 하루.. 이틀.. 밤새고 또 새고 고생하고 또 하고 눈물 나겠네요 ㅠㅠ 다시 말해 이러한 개념 자체를 알고 있는 것 자체가 중요하다는 것입니다. 의심을 해볼 수 있으니까요 !!

위의 소스 코드에서 배열을 출력하는 방법이 나오는데  이 개념은 C 언어에서 나오는 이야기입니다. 같은 배열을 여러가지 방법으로 사용할 수 있습니다.



<추상화>
추상화 영어로는 abstraction !! 사전적인 의미는 사물의 사실적 재현이 아니고 순수한 점ㆍ선ㆍ면ㆍ색채에 의한 표현을 목표로 한 그림을 의미합니다. 물론 이 뜻은 미술에서 사용하는 용어입니다.
그렇다면 컴퓨터에서 사용하는 의미는 통상적으로 주어진 문제나 시스템 중에서 중요하고 관계있는 부분만을 분리하여 간결하고 이해하기 쉽게 만드는 작업이라 합니다.
무슨 말인지 전혀 감 잡을 수 없군요. 그렇다면 예제를 살펴보면서 알아보아요.

#include <iostream.h>
#include <stdlib.h>

struct EMB
{
	int *item;
	int iNum;	
};

bool embInit(EMB *stVal)
{
	if(0 == stVal)
	{
		return false; // false : 문자 상수(리터럴)
	}

	stVal->item = 0;
	stVal->iNum = 0;

	return true;
}

bool embInit(EMB *stVal, unsigned int uiNum)
{
	if(0 == stVal)
	{
		return false; // false : 문자 상수(리터럴)
	}
	else if(0 == uiNum)
	{
		return false;
	}
	
	stVal->item = (int *)malloc(sizeof(int)*uiNum);
	if(0 == stVal->item)
	{
		return false;
	}
	
	stVal->iNum = uiNum;

	return true;
}

void embFree(EMB *stVal)
{
	if(0 == stVal)
	{
		return ;
	}
	
	if(0 == stVal->item)
	{
		return ;
	}

	free(stVal->item);
	
	stVal->item = 0;
	stVal->iNum = 0;
	
	return ;
}

int main()
{
	EMB obj;
	
	embInit(&obj);
	embInit(&obj, 300);
	embFree(&obj);
	
	return 0;
}

EMB 구조체 변수 obj 를 선언하여 함수를 통해서 obj 구조체를 접근합니다. main 함수에서 살펴보면 함수 호출하는 부분 외에는 아무것도 없지요. 이렇게 main 함수에서 직접적으로 원자료를 접근하여 수정하지 않습니다. 모두 함수를 호출하여 원자료를 접근합니다. 이 의미는 사용자가 자료에 어떻게 접근하여 값을 수정하는 수고를 할 필요가 없습니다. 함수를 호출하기만 하면 함수가 알아서 수고를 덜어 주지요. 

그럼 다시 사전적 의미를 살펴봅시다. 주어진 문제나 시스템 중에서 중요하고 관계있는 부분만을 분리하여 간결하고 이해하기 쉽게 만드는 작업이라 했지요. 주어진 문제 (시스템) 는 구조체에 수정하는 일이 되겠네요.  main 함수에서 살펴보면 구조체를 초기화 하는 작업을 함수에서 처리해 버리니 사용자는 초기화 하는 함수를 호출하기만 하면 되지요. 어떻게 초기화 하는지 알 필요도 없으며, 쉽게 이해 할 수 있지요. 이러한 작업을 하는 것이 "추상화 한다" 라고 할 수 있습니다. 

코드를 자세히 살펴보면서 진행해보아요.

bool embInit(EMB *stVal)
{
	if(0 == stVal)
	{
		return false; // false : 문자 상수(리터럴)
	}

	stVal->item = 0;
	stVal->iNum = 0;

	return true;
}

구조체를 초기화하는 함수입니다. 이 함수는 구조체에 0 으로 초기화 해주는 작업을 해줍니다. 여기서 C 언어에서 볼 수 없는 자료형을 볼 수 있습니다. 그건 바로 bool 형 입니다. bool 형은 true 와 false 의 문자 상수를 사용하는 자료형입니다. 이러한 true 와 false 는  문자 상수라 하고 리터럴이라고 합니다. C++ 언어에서 새로 생긴 자료형입니다. 참과 거짓을 판단을 할 때 사용할 수 있습니다. 코드 자체는 어려운 것이 없지요. 다음 함수를 살펴봅시다.

bool embInit(EMB *stVal, unsigned int uiNum)
{
	if(0 == stVal)
	{
		return false; 
	}
	else if(0 == uiNum)
	{
		return false;
	}
	
	stVal->item = (int *)malloc(sizeof(int)*uiNum);
	if(0 == stVal->item)
	{
		return false;
	}
	
	stVal->iNum = uiNum;

	return true;
}

구조체의 멤버의 int * 에 동적 할당을 하고 있습니다. 메모리를 할당하는 함수가 되겠습니다. 이렇게 메모리를 할당해야 하는 경우 사용자가 구현해야 한다면 정말 힘들겠죠? 이렇게 함수로 만들어져 있다면 함수의 사용 방법만 숙지한다면 쉽게 사용할 수 있습니다. 이 때 함수를 사용하는 사용자는 이 함수가 어떻게 동작하는지 알아야 할까요?? 함수의 사용 방법만 알고 있다면 알 필요가 없겠죠?? 
마지막 함수도 마저 살펴 봅시다.

void embFree(EMB *stVal)
{
	if(0 == stVal)
	{
		return ;
	}
	
	if(0 == stVal->item)
	{
		return ;
	}

	free(stVal->item);
	
	stVal->item = 0;
	stVal->iNum = 0;
	
	return ;
}

이 함수는 동적으로 할당된 메모리를 해제하는 역할을 합니다. 코드 자체는 어려움이 없습니다. 여기서도 마찬가지로 메모리를 해제하는 방법을 알 필요가 없습니다. 그저 이 함수의 사용 방법만 알고 있다면 이 함수를 호출하여 해제하면 됩니다. 그리고 main 함수에서는 구조체에 직접적으로 수정하는 일이 없습니다. 전부 함수에서 초기화 하고 메모리를 할당받고 해제하지요. 즉 main 함수에서는 구조체를 간접적으로 접근합니다.

하나의 기법이라 할 수 있습니다. 솔직히 main 함수에서 직접 접근하여 수정해도 됩니다. 그런데 왜?? 이렇게 사용하는가??? 의문을 가질 수 있게죠.. 그것은 직접 접근하다보면 버그나 오류가 발생하게 되면 문제가 커집니다. 그러나 함수를 이용하여 간접적으로  접근한다면 오류나 버그의 발생 빈도를 줄일 수 있게됩니다. 단, 조건이 있습니다. 함수가 정상적인 동작을 해야합니다. 또한 함수에 문제가 발생하면 함수 내부만 수정하면 됩니다.

정리를 해보자면 중요한 기능을 함수로 분리하여 간결해 지며, 함수를 통해 간접적으로 자료를 접근하여 오류를 줄일 수 있습니다. 추상화라는 의미를 사용하는 것은 이러한 함수가 어떻게 동작하는지 구체적으로 모르지만 어떠한 기능을 하는 함수인지는 알 수 있습니다. 이러한 측면으로 본다면 미술의 사전적 의미와 유사합니다. 사물의 사실적 재현이 아닌 순수한 점ㆍ선ㆍ면ㆍ색채에 의한 표현을 목표로 한 그림을 의미한다 했죠. 사실적 재현이 아니다. 즉 함수의 기능이 구제적으로 모른다는 의미와 유사합니다. 순수한 점ㆍ선ㆍ면ㆍ색채에 의한 표현을 목표로 한다는 것 에서는 함수의 반환형 인자 그리고 어떠한 기능을 하는지를 아는가를 목표로 한다라고 대치할 수 있겠습니다. 

728x90