[컴파일러] 바인딩이란..정적바인딩,동적바인딩 구분은..?

gyxor의 이미지

프로그래밍언어론 책에..
"바인딩(binding)은 일반적인 의미에서, 속성과 개체 또는 연산과 기호를 연관(association)시키는 것이다." 라고 나와있습니다.

프로그램의 변수의 경우 타입이 결정되는것, 값이 결정되는것을
바인딩으로 이해했습니다.

"바인딩이 실행시간 전에 일어나고, 프로그램 실행과정에서 변하지 않은 상태로 유지된다면 그 바인딩은 정적바인딩 이다.
바인딩이 실행시간 중에 일어나거나 프로그램 실행 과정에서 변경될 수 있다면, 그 바인딩은 동적바인딩이다."
라고 나와있습니다.
그리고서 Javascript의

list = [10.2 , 3.5]
...
list = 47

문장은 list변수가 중도에 다른 타입으로 바인딩 됐으므로
동적바인딩의 한 예가 된다고 나와있습니다.
여기까지는 이해가 되는데요..

"동적타입 바인딩에서는 타입이 선언문에 명세되지 않으며, 그 이름 철자로 부터도 결정될 수 없다. 대신 배정문에서 값이 변수에 배정될 때,
타입이 변수에 바인딩된다. 즉, 배정문이 실행될 때 배정 받는 변수는 배정문의 우변에 있는 값, 변수, 또는 식의 타입에 바인딩된다."
라고 나와있습니다. 이부분이 이상합니다.

예로...위 예문의 list = 47 과 같은 경우이지요..

그런데 이것이 왜 동적타입바인딩의 특성이 되는것인지 모르겠습니다.
실행시간동안에 타입이 결정되거나 변경된다는 동적타입바인딩의 정의와
배정문의 RHS를 보고서 타입을 유추하는것과 무슨 관련이 있는지 모르겠습니다.
첫째,
정적바인딩일때도 타입을 유추해서 사용하는것은 일어날 수 있는것 아닌가요??

"마지막으로, 변수에 동적 타입바인딩을 사용하는 언어는 흔히 컴파일러보다는 순수 인터프리터를 사용하여 구현되어야 한다. 컴파일 시간에 피연산자 타입이 알려지지 않은 기계코드 명령어를 생성하는 것은 가능하지 않다."
라는 부분이 이상합니다. 물론 두번째 문장이 맞는 말이지만..

둘째,
타입이 알려지지 않은 변수를 사용하는것은 컴파일러에서 뿐만아니라 인터프리터에서도 불가능한것 아닌가요?
이게 왜 동적바인딩에서 컴파일러 대신 인터프리터를 써야하는 이유가 되는지 모르겠습니다.

두가지 설명부탁드립니다.

익명 사용자의 이미지

gyxor wrote:
프로그래밍언어론 책에..
"바인딩(binding)은 일반적인 의미에서, 속성과 개체 또는 연산과 기호를 연관(association)시키는 것이다." 라고 나와있습니다.

프로그램의 변수의 경우 타입이 결정되는것, 값이 결정되는것을
바인딩으로 이해했습니다.

"바인딩이 실행시간 전에 일어나고, 프로그램 실행과정에서 변하지 않은 상태로 유지된다면 그 바인딩은 정적바인딩 이다.
바인딩이 실행시간 중에 일어나거나 프로그램 실행 과정에서 변경될 수 있다면, 그 바인딩은 동적바인딩이다."
라고 나와있습니다.
그리고서 Javascript의

list = [10.2 , 3.5]
...
list = 47

문장은 list변수가 중도에 다른 타입으로 바인딩 됐으므로
동적바인딩의 한 예가 된다고 나와있습니다.
여기까지는 이해가 되는데요..

"동적타입 바인딩에서는 타입이 선언문에 명세되지 않으며, 그 이름 철자로 부터도 결정될 수 없다. 대신 배정문에서 값이 변수에 배정될 때,
타입이 변수에 바인딩된다. 즉, 배정문이 실행될 때 배정 받는 변수는 배정문의 우변에 있는 값, 변수, 또는 식의 타입에 바인딩된다."
라고 나와있습니다. 이부분이 이상합니다.

예로...위 예문의 list = 47 과 같은 경우이지요..

그런데 이것이 왜 동적타입바인딩의 특성이 되는것인지 모르겠습니다.
실행시간동안에 타입이 결정되거나 변경된다는 동적타입바인딩의 정의와
배정문의 RHS를 보고서 타입을 유추하는것과 무슨 관련이 있는지 모르겠습니다.
정적바인딩일때도 타입을 유추해서 사용하는것은 일어날 수 있는것 아닌가요??

맞게 이해하신것 같은데요? 정적 바인딩일때는 이렇지 않다는 말은 없지 않나요?

gyxor의 이미지

변수선언의 두가지 방법
명시적선언 (explicit declaration)
ex> c언어의 int i; 같이 타입이 명시적으로 선언되는 경우
묵시적선언 (implicit declaration)
ex>"Fortran에서..식별자가 I,J,K,L,M,N의 문자로 시작되면 Integer타입으로
묵시적으로 선언되고, 그렇지 않으면 Real 타입으로 묵시적으로 선언된다."
이런 내용이 있습니다.

이렇게 변수선언에 있어서 두가지 방법이 있는데..
Javascript에서 처럼
list = [10.2 , 4.2]
list = 57
이렇게 값에 의해서 변수 타입이 바인딩되는(유추되는) 경우..
이것은 위에서 나온 것처럼..
================================================================================
"동적타입 바인딩에서는 타입이 선언문에 명세되지 않으며, 그 이름 철자로 부터도 결정될 수 없다. 대신 배정문에서 값이 변수에 배정될 때,
타입이 변수에 바인딩된다. 즉, 배정문이 실행될 때 배정 받는 변수는 배정문의 우변에 있는 값, 변수, 또는 식의 타입에 바인딩된다."
================================================================================
동적타입 바인딩의 특징이 되는것이 아니라.. 묵시적선언의 방법으로 봐야 하는것 아닌가요?
즉,
동적타입바인딩에서도 명시적 선언
예륻들면, 언어를 작성하기에 따라서
array list = [10.2 , 4.2]
integer list = 57
이렇게 명시적으로 선언을 하면서.. 동적바인딩을 할 수 도 있는게 아닌가요?(물론 이런 언어가 존재 하는지는 모르겠지만요..)
왜 이론상으로..동적바인딩에서는 타입이 선언문에 명세되지 않고 그 이름 철자로 부터도
결정될 수 없다!!! 라고 제한하고 있는지 모르겠습닌다.
설명부탁드립니다.

seoleda의 이미지

gyxor wrote:

프로그래밍언어론 책에.."바인딩(binding)은 일반적인 의미에서, 속성과 개체 또는 연산과 기호를 연관(association)시키는 것이다." 라고 나와있습니다.

맞습니다.

gyxor wrote:

"바인딩이 실행시간 전에 일어나고, 프로그램 실행과정에서 변하지 않은 상태로 유지된다면 그 바인딩은 정적바인딩 이다.
바인딩이 실행시간 중에 일어나거나 프로그램 실행 과정에서 변경될 수 있다면, 그 바인딩은 동적바인딩이다."

여기까지도 맞습니다.

gyxor wrote:

"동적타입 바인딩에서는 타입이 선언문에 명세되지 않으며, 그 이름 철자로 부터도 결정될 수 없다. 대신 배정문에서 값이 변수에 배정될 때,
타입이 변수에 바인딩된다. 즉, 배정문이 실행될 때 배정 받는 변수는 배정문의 우변에 있는 값, 변수, 또는 식의 타입에 바인딩된다."

오해의 소지가 있는 표현같습니다. "동적타입 바인딩에서는 타입을 선언문에 반드시 명세해야 할 필요는 없습니다" 라고 해야 정확한 표현 같습니다.
또한 우변에 있는 값. 변수 또는 식의 타입에 바인딩된다라는 얘기는 묵시적 형변환과 혼돈을 일으킬 만한 표현 같습니다. 틀린 얘기는 아니지만 우변의 값을 컴파일 시간에 결정할 수 없는 경우는 동적바인딩이 필요할 것이지만, 우변의 타입이 컴파일 시간에 결정되는 경우는 정적 바인딩을 할것입니다.

그럼 우변의 타입을 컴파일 시간에 결정할 수 없는 경우도 있는가? 혹은 구지 실행시간에 타입을 결졍해야 하는가? 라는 질문이 있겠지요.

결론은 실행시간에 타입이 결정되는경우, 프로그래밍을 쉽게 할 수 있습니다. 예를들어, 여러가지 도형(사각형, 원, 삼각형 등)을 그리는 프로그램을 작성하는 경우, 사용자가 어떤 도형을 입력할지 컴파일 시간에는 모릅니다. 따라서, "+"를 두 도형의 넓이의 합을 구하는 연산이라고 정의하고,

넓이 = 첫번째입력도형 + 두번째입력도형;

와 같은 코드가 동적타입바인딩을 지원하는 언어에서는 가능합니다. 어떠한 언어가 정적 타입바인딩만을 지원한다면 많은 if문이 필요하겠지요.

gyxor wrote:

"마지막으로, 변수에 동적 타입바인딩을 사용하는 언어는 흔히 컴파일러보다는 순수 인터프리터를 사용하여 구현되어야 한다. 컴파일 시간에 피연산자 타입이 알려지지 않은 기계코드 명령어를 생성하는 것은 가능하지 않다."

첫번째 문장은 저자의 주장입니다. C++의 virtual 키워드를 사용하여 클래스를 잘 설계한다면, 동적 타입바인딩을 구현할 수 있습니다. 이부분은 설명하려면 길어지니 C++의 virtual 키워드를 설명한 책을 보시길 바랍니다. 또한 java에서도 임의의 클래스를 배열에 담을 수 있으며, 배열에 들어있는 클래스의 유형을 알아내는 연산자도 존재합니다. (어떠한 연산자인지는 기억이 잘... ^^)

p.s. 어떤 책인지는 모르겠지만, 인용된 부분으로 판단하건데 오래된 책이거나 저자도 혼돈하고 있는듯 합니다.

jj의 이미지

책에 쓰인 내용은, 번역하면서 잘못됐을지도 모르고, 아무튼 상당히 조심하게 읽어야 할듯 하군요.

seoleda wrote:

첫번째 문장은 저자의 주장입니다. C++의 virtual 키워드를 사용하여 클래스를 잘 설계한다면, 동적 타입바인딩을 구현할 수 있습니다. 이부분은 설명하려면 길어지니 C++의 virtual 키워드를 설명한 책을 보시길 바랍니다. 또한 java에서도 임의의 클래스를 배열에 담을 수 있으며, 배열에 들어있는 클래스의 유형을 알아내는 연산자도 존재합니다. (어떠한 연산자인지는 기억이 잘... ^^)

p.s. 어떤 책인지는 모르겠지만, 인용된 부분으로 판단하건데 오래된 책이거나 저자도 혼돈하고 있는듯 합니다.

그런데, C++의 virtual, java의 일반적인 method(not static, not final) 이 동적 '타입바인딩'이라고 할수 있을까요? 저도 좀 헤깔리는데, 이 경우 타입바인딩이라기 보다는, 동적 method 바인딩(dynamic dispatch)이 아닐까요? 타입은 컴파일타임에 슈퍼클래스의 타입으로 정해지는게 아닐까요? 이는 분명 python따위의 언어와는 다를것 같네요.

--
Life is short. damn short...

seoleda의 이미지

Quote:

그런데, C++의 virtual, java의 일반적인 method(not static, not final) 이 동적 '타입바인딩'이라고 할수 있을까요? 저도 좀 헤깔리는데, 이 경우 타입바인딩이라기 보다는, 동적 method 바인딩(dynamic dispatch)이 아닐까요? 타입은 컴파일타임에 슈퍼클래스의 타입으로 정해지는게 아닐까요? 이는 분명 python따위의 언어와는 다를것 같네요.

네.. 컴파일타임에 슈퍼클래스의 타입으로 정해지며, C++을 설명한 책에는 타입바인딩이라는 언급이 없지만 바인딩이라는 것이 "연산(method)과 기호를 연관시키는 것이다." 라는 관점에서 본다면, 서브클래스들 사이에서는 동적 타입(클래스)바인딩이라고 부를 수 있지 않을까요?

예를들어, 수퍼클래스로 도형을 만들고 그 서브클래스로 삼각형과 원을 만들고, draw()라는 연산(method)를 정의 합니다. 그럼, 도형이라는 (클래스)변수는 실행시간에 삼각형으로도, 사각형으로도 쓰일수 있으며, 도형.draw()라는 연산은 실행시간에 삼각형.draw()로도 원.draw()로도 해석될 수 있으므로 연산(draw)와 기호(삼각형, 사각형)가 실행시간에 연관된다고 볼 수 있지 않나요?

위 얘기가 "C++가 동적 타입바인딩을 지원하는 언어다" 라는 얘기는 아니고요, "동적 method 바인딩으로 동적 타입바인딩을 구현할 수 있다" 정도로 생각할 수 있지 않을까요?

jj의 이미지

seoleda wrote:

위 얘기가 "C++가 동적 타입바인딩을 지원하는 언어다" 라는 얘기는 아니고요, "동적 method 바인딩으로 동적 타입바인딩을 구현할 수 있다" 정도로 생각할 수 있지 않을까요?

물론이죠.

--
Life is short. damn short...

gyxor의 이미지

C++은 동적바인딩(dynamic binding)을 지원하는 언어가 아닌가요?
성안당 C++책 689p에
[동적결합의 작동]
"멤버함수에 대해서만 동적결합을 사용할 수 있다." 라고 나와있습니다.
클래스상에서 멤버변수에는 virtual을 적용할 수 없다는 그 이야기를 하고 있는것 같습니다.

#include<iostream>
using namespace std;

class First
{
public:
	virtual void show(){
		cout << "-First-" << endl;
	}
};

class Second : public First
{
public:
	void show(){
		cout << "-Second-" << endl;
	}
	void test(){
		cout << "test" << endl;
	}
};

class Third : public Second
{
public:
	void show(){
		cout << "-Third-" << endl;
	}
};

int main() 
{ 
	First *point;	
    First first;
	Second second;
	Third third;
	
	int input;
	cin >> input;
    switch(input)
	{
	case 1:
	point = &first;
	(*point).show();
	break;
    
	case 2:
	point = &second;
	(*point).show();
    //(*point).test(); 오류!!!

	break;

	case 3:
	point = &third;
	(*point).show();
	break;
	}
	return 0;
} 

virtual 키워드를 사용해서 부모클래스 포인터를 사용하더라도 자식클래스에서
재정의된 메소드가 호출될 수 있도록 하는... 가상함수 소스입니다.
(극히 특수한 상황에서 제한된 기능만을 수행하는 가상함수가 왜 필요한지는
잘 모르겠지만..
자식클래스의 인스턴스 주소를 매핑하는 상황이니까..그냥 부모클래스의 포인터를 쓰지 말고.. (형 격상 이라고 하는..)
원칙에 맞게 자식클래스의 포인터를 쓰면 되지 않나 생각했습니다.
예,
Second s;
Second *p = &s; )
본론으로 돌아와서..
어쨋든, 동적바인딩의 한 예로 볼 수 있습니다.
마찬가지로..(이제부터는 저의 생각입니다.)
#include<iostream>
using namespace std;

int main() 
{ 
float i = 48;
void *p = &i;

int input; 
cin >> input;
if(input == 1) cout << *(char *)p;
else           cout << *(float *)p;

return 0; 
}

위 소스에서 변수p는 포인터 형 변수로 정적 바인딩으로 선언이 되어있는데요..
(최소한 포인터 형 변수라는 것은 void * 를 통해서 알수있지 않습니까?)
포인터를 참조 했을 경우에 어떤 데이터형을 가지게 될지는 동적 바인딩 됩니다.
(물론 이것이 결정이 안된 상태로 사용하는 것은 에러처리됩니다.)
ex> *p

#include<iostream>
using namespace std;

template<typename Type>
class Test
{
public:
	Type value;
};

int main() 
{ 
	int input;
	cin >> input;
	if(input == 1){
		Test<int> te;
		te.value = 10;
	}
	else{
		Test<char *> te;
		te.value="TEST";
	}
    return 0;
} 

템플릿도 마찬가지로 동적바인딩입니다.

지금까지의 내용이 맞다면..
최초에 질문했던..
첫째,
"With dynamic type binding, the type is not specified by a declaration statement,
nor can it be determined by the spelling
of its name. Instead, the variable is bound to a type when it is assigned a value
in an assignment statement. When the assignment statement is executed, the variable
being assigned is bound to the type of the value of the expression on the right side of the assignment."
"동적타입 바인딩에서는 타입이 선언문에 명세되지 않으며, 그 이름 철자로 부터도 결정될 수 없다. 대신 배정문에서 값이 변수에 배정될 때,
타입이 변수에 바인딩된다. 즉, 배정문이 실행될 때 배정 받는 변수는 배정문의 우변에 있는 값, 변수, 또는 식의 타입에 바인딩된다."

이 내용 잘못된 것 아닌가요?
(위 예제 소스에선 동적타입바인딩이어도 타입이 선언문에 명시가 되는데요..)

둘째,
"Finally, languages that have dynamic type binding for variables must be implemented
using pure interpreters rather than compilers. It is not possible to create machine
code instructions whose operand types are not known at compile time."

"마지막으로, 변수에 동적 타입바인딩을 사용하는 언어는 흔히 컴파일러보다는 순수 인터프리터를
사용하여 구현되어야 한다. 컴파일 시간에 피연산자 타입이 알려지지 않은 기계코드 명령어를 생성하는 것은 가능하지 않다."

번역판에선 "컴파일러보다는" 으로 비교로 해석되었지만 원문을 보면
"rather than" 입니다. 컴파일러는 아예 아니라는 얘기입니다.

하지만 마찬가지로.. 동적타입바인딩 방식이 컴파일러 방식인 C++에서 구현되는것 아닌가요?
위 소스에서 컴파일시간에 피연산자의 타입은 모르지만 if문이나 switch-case
문의 모든 경우를 코드로 생성해주면.. 컴파일 시간에도 동적바인딩이 구현되는것 아닌가요?

2가지 질문입니다.
잘못된 점 지적 부탁드립니다...

서지원의 이미지

gyxor wrote:

템플릿도 마찬가지로 동적바인딩입니다.

템플릿은 gyxor님께서 처음 정의하신 방식으로 생각한다면 동적 바인딩이 아니라 정적 바인딩입니다. (사실 Template은 runtime에 특별히 일어나는 일이 전혀 없기 때문에 동적인 특성이 없습니다.)

처음에 책으로부터 인용하신 정의를 보면,

gyxor wrote:

"바인딩이 실행시간 전에 일어나고, 프로그램 실행과정에서 변하지 않은 상태로 유지된다면 그 바인딩은 정적바인딩 이다.
바인딩이 실행시간 중에 일어나거나 프로그램 실행 과정에서 변경될 수 있다면, 그 바인딩은 동적바인딩이다."

템플릿에서 타입은 컴파일 타임에 결정되기 때문에 정적 바인딩입니다.

gyxor님께서 예로 드신 template코드를 보면,

#include<iostream> 
using namespace std; 

template<typename Type> 
class Test 
{ 
public: 
   Type value; 
}; 

int main() 
{ 
   int input; 
   cin >> input; 
   if(input == 1){ 
      Test<int> te; 
      te.value = 10; 
   } 
   else{ 
      Test<char *> te; 
      te.value="TEST"; 
   } 
    return 0; 
}

이것은 dynamic binding이 아닙니다. te에 대한 타입이 if문에 따라서 두 가지로 컴파일 타임에 결정되고, 실행시에는 te의 type에 대한 결정이 이루어지지 않습니다.

SuperType v;
if (case1) {
  v = SubType1();
}
else if (case2) {
 v = SubType2();
}
v.doOperation();

위의 (Java로 된) 예의 경우라면 runtime에 variable과 type의 binding이 이루어지므로 (제한적으로) dynamic binding이라고 볼 수 있습니다. 제한적이라는 말을 쓴 이유는 위의 예에서 v가 가질 수 있는 type들이 SuperType의 subtype에 제한되기 때문입니다.
v=None
if case1: v = Type1()
elif case2: v = Type2()

v.doOperation()

위의 (Python으로 된) 예의 경우에는 variable v의 type이 (제한없이) 런타임에 binding됩니다.

책에서 언급한 내용은 variable과 type 사이의 binding에 관한 내용이고, C++에서 dynamic binding에 해당하는 부분은 method name과 실제 호출되는 method body사이 입니다. 위에서 이미 다른 분들이 언급하신 내용이죠. (제한적인 의미에서는 variable과 type 사이의 binding도 dynamic하죠.)

void 포인터를 사용하신 예를 보면,

#include<iostream> 
using namespace std; 

int main() 
{ 
float i = 48; 
void *p = &i; 

int input; 
cin >> input; 
if(input == 1) cout << *(char *)p; 
else           cout << *(float *)p; 

return 0; 
} 

이 역시 dynamic binding의 예가 아닙니다. 사용자의 input에 따라서 *p가 char 형식으로도 출력이 되었다가 float형식으로 출력이 되기도 하는 것으로부터 dynamic binding이지 않느냐는 것이죠? 이 역시 p가 char*으로 다룰지, float*으로 다룰지는 컴파일 타임에 결정되며, 런타임에 이루어지지 않습니다. 런타임에 type정보가 variable p에 binding되었다면 cout으로 출력하는 if.. else 문 이후에 p로부터 p의 type이 char* 인지 float*인지를 알 수 있어야 하는데 그렇지 않지 않습니까?

Dynamic binding은 기본적으로 runtime에 어떤 변수로부터 그 type을 알 수 있는 경우에만 가능하다고 보면 될 것 같습니다.

아, 그리고 저는 dynamic binding이 interpreter가 없이도 구현 가능하다고 보기 때문에, 두번째 질문은 개인적으로 책이 잘못된 것이 아닌가 생각합니다.

gyxor의 이미지

서지원 wrote:

책에서 언급한 내용은 variable과 type 사이의 binding에 관한 내용이고, C++에서 dynamic binding에 해당하는 부분은 method name과 실제 호출되는 method body사이 입니다.

예 맞습니다.
그런데, 메소드에 관한 것이든 type에 관한 것이든
dynamic binding은 개념은 같다고 생각합니다.

C++에서 클래스의 메소드에 있어서...
virtual function 을 쓰는것은 dynamic binding 이라고 했습니다.
첫번째 소스는 컴파일 방식으로 처리되므로 컴파일 시간에 1,2,3 입력에 따르는 모든 경우가 미리 코드로 만들어집니다.
실행시간에는 어떠한 코드도 추가 될 수 없고 이미 주어진 세가지 경우중 한가지로 진행이 되는것입니다.
저도 처음엔 이런것도 dynamic binding으로 볼 수 있나 생각이 들었지만.. 책에서 그렇다고 하니까 이런 개념도 dynamic binding으로 보고 다른 예 들을 찾아본것입니다.
나머지 2가지 소스도 마찬가지 방식입니다. 그런데..

서지원 wrote:

이것은 dynamic binding이 아닙니다. te에 대한 타입이 if문에 따라서 두 가지로 컴파일 타임에 결정되고, 실행시에는 te의 type에 대한 결정이 이루어지지 않습니다.

말씀하신 대로 이것이 dynamic binding이 아니라면
virtual funcion은 어떻게 dynamic binding이 되나요?

또한 예로 드신

SuperType v; 
if (case1) { 
  v = SubType1(); 
} 
else if (case2) { 
 v = SubType2(); 
} 
v.doOperation(); 

반례로 드신 자바 코드도 ..
컴파일 타임에 case1 과 case2의 경우를 모두 코드로 만들어 놓고
실행타임에는 주어진 2개의 경로중 선택해서 가는것! 만 이뤄지지 않나요? 결국 제가 예로 든것과 동일한 개념 아닌가요?

그리고 만일..
if문이나 switch case문에서 모든 경우에 대해서 컴파일 타임에 코드로 만들어 놓고 실행타임에는 선택해서 실행만 하는 지금까지의 내용이 dynamic binding 이 아니라면 ..

서지원 wrote:

아, 그리고 저는 dynamic binding이 interpreter가 없이도 구현 가능하다고 보기 때문에,

컴파일러 방식으로 dynamic binding을 구현하는게 어떻게 가능할 수 있는지 궁금합니다..
답변부탁드립니다.
익명 사용자의 이미지

dynamic binding이란 우리가 부르는 "이름"과 그 "본체"에 대한 결합이 실행시에 동적으로 일어난다는 것을 의미합니다.

gyxor님께서 드신 예와 제가 든 예를 비교해보죠.

gyxor wrote:

#include<iostream> 
using namespace std; 

template<typename Type> 
class Test 
{ 
public: 
   Type value; 
}; 

int main() 
{ 
   int input; 
   cin >> input; 
   if(input == 1){ 
      Test<int> te; 
      te.value = 10; 
   } 
   else{ 
      Test<char *> te; 
      te.value="TEST"; 
   } 
    return 0; 
} 


예를 들어 input이 1이 들어온 경우를 생각해 보면, input이 1인 순간에 Test<int> type인 변수 te가 새로 생기는 것이지 어떤 type을 모르던 te라는 변수에 동적으로 Type<int>라는 type이 binding된 것이 아닙니다.

위의 코드는 아래 내용과 의미상 동일하며, 이는 dynamic binding이 아님은 명백합니다.

class Foo{
public:
  int value;
}
class Bar{
public:
  char *value;
}
int main() 
{ 
   int input; 
   cin >> input; 
   if(input == 1){ 
      Foo var; 
      var.value=10; 
   } 
   else{ 
      Bar var;
      var.value="TEST"; 
   } 
    return 0; 
} 

서지원 wrote:

SuperType v; 
if (case1) { 
  v = SubType1(); 
} 
else if (case2) { 
 v = SubType2(); 
} 
v.doOperation(); 


그러나 제가 든 예에서는 우선 type이 SuperType "일 수 있는" 변수 v가 있으며, if.. else문을 거치고 나면 v가 SubType1일지, SubType2일지가 결정됩니다. 이 결정은 실행시에 일어나기 때문에 dynamic binding이라고 부릅니다.

if..else가 있는 코드를 예로 드니까 (dynamic binding과는 관련없이) gyxor님께서는 실행시에 어떤 "결정"이 일어나니까 dynamic binding이 아니냐고 생각하시는 것 같아서 예를 하나 더 듭니다.

// class 정의
class Printable {
...
  void printMe(Printer p) {
    p.print(this.toString());
  }
}

Interface Printer {...}
class NetworkPrinter extends Printer {...}
class NullPrinter extends Printer {...}
class ElectricPrinter extends Printer {...}
// class 정의 끝

Printable document = new Printable();
NetworkPrinter  p1 = new NetworkPrinter();
NullPrinter     p2 = new NullPrinter();
ElectricPrinter p3 = new ElectricPrinter();

document.printMe(p1);
document.printMe(p2);
document.printMe(p3);

위의 예에서는 printMe에서의 변수 p의 type이 뭐가 될지는 실제 p1으로 불릴지, p2, p3로 불릴지에 따라 달라집니다. 따라서 이 경우는 dynamic binding이 맞습니다. (앞서 이야기한 "제한적인" 것이긴 하지만)

variable과 type이 dynamic binding이 된다면, type에 의한 다형성(polymorphism)이 가능하다고 보면 대강 맞지 않나 생각합니다.

gyxor wrote:

컴파일러 방식으로 dynamic binding을 구현하는게 어떻게 가능할 수 있는지 궁금합니다..
답변부탁드립니다.

가장 간단하게는, 인터프리터의 경우, bytecode를 fetch/decode/execute를 하는 loop이 항상 존재합니다(당연하지요.) 이 bytecode를 fetch/decode/execute하는 코드도 native compilation이 가능할텐데, 그렇게 해서 bytecode 대신에 사용하면 가능하겠지요. 실제로 Lisp 컴파일러/인터프리터의 경우에 native compilation을 지원하는 것으로 알고 있습니다. (native compilation을 하는 경우에는 class의 hierarchy를 runtime에 바꾸거나 하는 것은 지원하지 않습니다.) (Lisp은 dynamic binding을 지원하는 대표적(?)인 언어중의 하나이지요.)
gyxor의 이미지

예로 드신 내용과 동일한 내용입니다.

class Robot{
	void ahead(Robot t){
	}
}
class M1tank extends Robot{
    void ahead(){
		System.out.println("M1tank.ahead()");
	}
}
public class Test{
	public static void main(String[] args)
	{
		M1tank m = new M1tank();
		Robot r = new Robot();
		r.ahead(m);
	}
}

자바에서 동적바인딩에 관한 예로 등장하는 형격상에 관한 소스입니다.
(C++과는 달리 특별히 가상함수 개념을 적용하지 않아도 동적 바인딩이 지원이 되 편리한것 같습니다.)
그런데..제가 말씀드리고 싶은것은..
Robot 클래스에서 ahead함수의 파라미터인
Robot t
즉, t변수가 동적으로 바인딩된다는것은 알겠습니다.
그런데 여기서 t또한 앞서의 경우처럼..
비록 자신이 무슨 타입이 될지는 컴파일 타임에 알 수 없지만
적어도 자신이 될 수 있는 타입의 후보들은 컴파일 타임에 정해놓는다는 것입니다. Robot 클래스는 어떤 클래스가
자신을 상속했는지 컴파일타임에 알고 있습니다. M1tank 클래스가 자신을 상속했고 그것의 인스턴스는 자신이 받아들일 수 있는 후보로 놓는것입니다.
만일에 extends Robot을 없애면 Robot클래스는 M1tank클래스가 자신을 상속한 클래스가 아니므로 그의 인스턴스인 m은 받아들일 수 없다고 표시합니다.
Test.java:15: ahead(Robot) in Robot cannot be applied to (M1tank)
                r.ahead(m);
                 ^

결국, 컴파일 타임에 Robot의 인스턴스인 t는 자신이 어떤 데이터 형에 바인딩 되어야 하는지 .... 그 후보들을 알고 있다는 것입니다.
물론 실제 바인딩은 실행시간에 일어나지만요..
마찬가지로..
#include<iostream> 
using namespace std; 

int main() 
{ 
float i = 48; 
void *p = &i; 

int input; 
cin >> input; 
if(input == 1) cout << *(char *)p; 
else           cout << *(float *)p; 

return 0; 
} 

이 코드에서도 컴파일 타임에!
p라는 포인터변수는 자신이 가질 수 있는 타입의 후보를 정해놓은 것입니다.
컴파일 타임에는 결정을 할 수 없죠..
실행타임이 지나봐야
char * 가 되는지 float *가 되는지 알 수 있습니다.
이런 의미에서..
동일한 개념이 아닌가 했습니다..
답변부탁드립니다..
jj의 이미지

jj wrote:
seoleda wrote:

위 얘기가 "C++가 동적 타입바인딩을 지원하는 언어다" 라는 얘기는 아니고요, "동적 method 바인딩으로 동적 타입바인딩을 구현할 수 있다" 정도로 생각할 수 있지 않을까요?

물론이죠.

라고 했지만, (토론이 정확 포말하게 가서... 말바꾸기인가...ㅡ.ㅡ) 엄연히 dynamic method dispatch와 dynamic typing은 다른것이죠.

Template
서지원씨가 언급했듯이, 템플릿은 100% 컴파일타임 게임입니다. 확장후에 타입검사를 하는 macro정도로 생각할 수 있겠죠.

그리고 예로드신...

#include<iostream>
using namespace std;

template<typename Type>
class Test
{
public:
   Type value;
};

int main()
{
   int input;
   cin >> input;
   if(input == 1){
      Test<int> te;
      te.value = 10;
   }
   else{
      Test<char *> te;
      te.value="TEST";
   }
    return 0;
} 

에서 if/else 부분은 아래와 다를것이 전혀 없으므로, ... 생략

   if(input == 1){
      Test<int> te1;
      te1.value = 10;
   }
   else{
      Test<char *> te2;
      te2.value="TEST";
   }

subtype
C++, java 언어에서 사용되는 Subtype polymorphism(virtual 따위)은 정적 타입검사의 틀 안에서 다형성을 지원하는것이죠. 어떤 인터페이스를 구현하고 있는 클래스는 동적으로 결정되지만, 그래서 메소드 바인딩은 동적이지만, 어떤 인터페이스를 구현하고 있다는 말 자체가, 결국 그 타입을 가진다라는 말이되죠. 그리고 그건 컴파일타임에 결정되구요.

좀더 구체적으로 말하면 C++, java는 컴파일 타임에 존재하지 않으면 다형성 구현이 불가능하지요? 그런데 super class, abstract super class, interface이 결국 타입을 정의하거든요. 물론 뼈대만 정의할 수 있죠. 바인딩은 동적으로 되고... 그런데 python같은 언어는 어떤가요? interface가 없지요. 필요가 없지요. 코드에서 콜하는 메소드만 있으면 되는거죠. 있기만 하면...

결론적으로 말씀하신대로 동적인 특성이 없는건 아니죠. 하지만 결코 완전히 동적은 아니죠?

컴파일
컴파일은 되겠지만, 인터프리팅 요소가 컴파일된 코드에 많이 녹아있겠지요....

추가글.

gyxor wrote:

#include<iostream> 
using namespace std; 

int main() 
{ 
float i = 48; 
void *p = &i; 

int input; 
cin >> input; 
if(input == 1) cout << *(char *)p; 
else           cout << *(float *)p; 

return 0; 
} 

이 코드에서도 컴파일 타임에!
p라는 포인터변수는 자신이 가질 수 있는 타입의 후보를 정해놓은 것입니다.
컴파일 타임에는 결정을 할 수 없죠..
실행타임이 지나봐야
char * 가 되는지 float *가 되는지 알 수 있습니다.
이런 의미에서..
동일한 개념이 아닌가 했습니다..
답변부탁드립니다..

Robot의 경우에, 컴파일 되는 시점에서 모든 서브클래스를 알 수 없죠. 컴파일 된 다음 만든 클래스도 있을 수 있구요. 단지 그 타입은 정적으로 Robot으로 정할 수 있겠죠. (혹은 그 서브클래스)

--
Life is short. damn short...

익명 사용자의 이미지

깊게 생각할 필요 없습니다.

동적바인딩, 정적바인딩은 학자들이 만들어낸 용어일 뿐입니다.

자신이 컴파일러를 만들고자 할 때 어떤식으로 구현을 하든 상관 없습니다.

동적과 정적이 섞인 경우도 많습니다.

또한 동적이 좋냐 정적이 좋냐는 그 누구도 확언할 수 없습니다.

나름대로의 장, 단점이 있으니까요.

그리고 어떤 특정한 언어의 컴파일러만 보고 "이건 동적이다, 이건 정적이다" 할 수 없습니다.

왜냐하면 구현한 사람 맘이니까요.

컴파일러를 직접 만들고 싶으시다면 동적, 정적 상관하시지 마시고 직접 만들어 보세요.

그래야지 왜 정적바인딩과 동적바인딩이 생겨났는지 알 수 있습니다. 아니면 프로그래밍 언어의 역사를 찾아보세요. 도움이 되실겁니다.

그럼, 이만.

어줍짢은 프로그래머였습니다.

doldori의 이미지

gyxor wrote:
#include<iostream> 
using namespace std; 

int main() 
{ 
float i = 48; 
void *p = &i; 

int input; 
cin >> input; 
if(input == 1) cout << *(char *)p; 
else           cout << *(float *)p; 

return 0; 
} 

이 코드에서도 컴파일 타임에!
p라는 포인터변수는 자신이 가질 수 있는 타입의 후보를 정해놓은 것입니다.
컴파일 타임에는 결정을 할 수 없죠..
실행타임이 지나봐야
char * 가 되는지 float *가 되는지 알 수 있습니다.
이런 의미에서..
동일한 개념이 아닌가 했습니다..
답변부탁드립니다..

이것과는 다른 개념이라고 봅니다. 컴파일 타임에 결정할 수 없는 것은 execution path일
뿐입니다. cout << *(char *)p가 어떤 함수를 호출할지는 컴파일 타임에 완전히 결정됩니다.
캐스팅을 한다는 것 자체가 이미 정적 바인딩임을 뜻하는 것입니다.
gyxor의 이미지

doldori wrote:

이것과는 다른 개념이라고 봅니다. 컴파일 타임에 결정할 수 없는 것은 execution path일
뿐입니다. cout << *(char *)p가 어떤 함수를 호출할지는 컴파일 타임에 완전히 결정됩니다.
캐스팅을 한다는 것 자체가 이미 정적 바인딩임을 뜻하는 것입니다.

예 맞습니다... 말씀하신 대로입니다.

SuperType v; 
if (case1) { 
  v = SubType1(); 
} 
else if (case2) { 
 v = SubType2(); 
} 
v.doOperation();

제가 ..
이 소스 또한 마찬가지로 컴파일타임에 다 결정될 수 있고
실행타임에 결정되는것은 execution path 뿐이라고
생각했었습니다.
그런데 한가지 중요한 사실을 인식 못하고 있었습니다.

컴파일타임에 코드를 생성하면서 함수!를 미리 실행시켜볼 수
없다는것 따라서 파라미터를 미리 전달해서 알려줄 수 없고!!
리턴 결과도 컴파일타임에 알 수 없다는것!!
결국 바인딩은 실행타임으로 넘어가야 된다는것...
동적바인딩 맞습니다..
(함수호출까지 있는 언어의 컴파일러를 제작해 봤다면 진작 이해했을 텐데요..)
그리고 앞서 제 소스들은 정적바인딩입니다..

답변 대단히 감사합니다.^^
ps:
하지만 메소드의 동적바인딩이라고 했던 virtual function은
가상함수 table을 이용한다는 이유로 동적이 되는게..좀 그렇습니다.

seoleda의 이미지

python이 어떤식으로 동적타입 바인딩을 구현했는지 모르겠지만, 제가 만일 동적타입바인딩을 지원하는 언어를 제작한다고 한다면, virtual function을 이용한 구현외에는 잘 떠오르지도 않습니다.

예를들면 variable라는 클래스를 만들고, 기본적인 연산자를 vritual function으로 선언한후, integer, float, string과 같은 기본적인 datatype을 variable을 상속하도록 설계하여 dynamic type binding을 구현하는것입니다. 또한 이런식으로 visual C++에서 variant type이 구현되었으리라 추측하고 있습니다.

Quote:
좀더 구체적으로 말하면 C++, java는 컴파일 타임에 존재하지 않으면 다형성 구현이 불가능하지요? 그런데 super class, abstract super class, interface이 결국 타입을 정의하거든요. 물론 뼈대만 정의할 수 있죠. 바인딩은 동적으로 되고... 그런데 python같은 언어는 어떤가요? interface가 없지요. 필요가 없지요. 코드에서 콜하는 메소드만 있으면 되는거죠. 있기만 하면...

이 부분에서는 python을 해보지 않아서 잘 모르지만 interface가 사용자에게만 보이지 않는것이 아닐까요? 컴파일러를 설계할때 "모든 클래스는 abstract class를 상속한다"라고 하면 datatype에 대한 평가가 모두 runtime에만 이루어 지게 될것입니다.

마지막으로,

Quote:
"Finally, languages that have dynamic type binding for variables must be implemented
using pure interpreters rather than compilers. It is not possible to create machine
code instructions whose operand types are not known at compile time."

이 부분에 대한 제 주장은 컴파일러에서도 조차 dynamic type binding이나 그에 준하는 기능이 필요하다는 것입니다. 이러한 기능이 존재하지 않는 컴파일러로 undo/redo 기능을 구현하거나 데이타베이스 프로그래밍을 하는것은 정말 악몽입니다. 없다고 해서 프로그래밍을 못하는 것은 아니나, 지금 처럼 쉽게 할 수는 없었을 것입니다.
violino의 이미지

Java에서 Object 으로 매개변수를 정의할땐 어떨까요?
이때도 동적 바인딩으로 봐야겠지요? 물론 아래의 정의와 같이 넓은 의미의 동적 바인딩으로 볼 때 말이죠.

Quote:
As we have already discussed, dynamic binding of messages to methods in an inheritance hierarchy is an essential part of object-oriented programming. ...
- Concept of programming languages, 5th ed, Robert W. Sebesta, Addison Wesley, page 467

vio:

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.