리눅스에서 GCC를 사용하고 있습니다.정적 및 동적 바인딩이 실제로 작동하려면 어떻게해야합니까? [C++]
저는 가상 기능을 사용하는 것을 알고 싶습니다.
가상 함수 사용 여부에 관계없이 정적 바인딩과 동적 바인딩이 어떻게 발생하는지보고 이해하려면 어떤 종류의 C++ 코드를 작성해야합니까?
어떻게 그들이 최종적으로 바인딩되었는지 그리고 프로세스 중에 정확히 무슨 일이 일어 났는지 "보는"방법?
리눅스에서 GCC를 사용하고 있습니다.정적 및 동적 바인딩이 실제로 작동하려면 어떻게해야합니까? [C++]
저는 가상 기능을 사용하는 것을 알고 싶습니다.
가상 함수 사용 여부에 관계없이 정적 바인딩과 동적 바인딩이 어떻게 발생하는지보고 이해하려면 어떤 종류의 C++ 코드를 작성해야합니까?
어떻게 그들이 최종적으로 바인딩되었는지 그리고 프로세스 중에 정확히 무슨 일이 일어 났는지 "보는"방법?
다음은 예입니다. 함수를 가상 함수로 설정하여이 코드를 작성하고 실행할 수 있습니다. 가상 동작, 동적 디스패치, 동적 바인딩을 얻으려면 전 처리기 매크로 IS_VIRTUAL
을 정의하여 빌드하십시오. 정적 바인딩을 보려면 해당 매크로를 정의하지 않고 빌드하십시오.
#include <iostream>
#if defined(IS_VIRTUAL)
#define CONDITIONAL_VIRTUAL virtual
#else
#define CONDITIONAL_VIRTUAL
#endif
struct A {
CONDITIONAL_VIRTUAL void foo() { std::cout << "A\n"; }
};
struct B : A {
CONDITIONAL_VIRTUAL void foo() { std::cout << "B\n"; }
};
// global objects
A a; B b;
enum object_type { get_A, get_B };
A *get_object(object_type t) {
switch (t) {
case get_A: return &a;
case get_B: return &b;
}
}
int main() {
std::cout << "Choose A or B: ";
char c;
std::cin >> c;
A *x = get_object(c == 'A' ? get_A : get_B);
x->foo();
}
상기 바인딩은 x->foo()
의 평가와 관련있다. 컴파일러는 해당 표현식에 대해 실행할 코드를 찾아야합니다. 정적 바인딩과 동적 바인딩 모두에서 컴파일러는 x
을보고 그 유형이 A*
이라고보고 있으므로 struct A
을보고 foo()
선언을 찾습니다. 컴파일러를 정적 바인딩으로
는 foo()
이 virtual
아니라는 것을 발견, 그래서 컴파일러는 앞서가는 그 foo()
메소드를 호출하는 코드를 생성합니다. 단순한.
컴파일러는 virtual
으로 표시하는 방법을보고하고, 따라서 컴파일러 대신에, 실행시에, 호출하는 방법을 선택할 개체 x
와 연관된 함수 포인터의 테이블을 사용하는 코드를 생성하고 어떤 방법이든 찾는다. 컴파일러는 또한 다른 곳에서 코드를 생성하여 a
및 b
전역 개체에 대한 테이블을 만듭니다. 전역 a
개체의 경우 테이블의 대상을 A::foo()
으로 지정하고 b
의 경우 테이블의 대상을 B::foo()
으로 만듭니다. 따라서 x
이 b
개체를 가리킨다면 테이블 검색은 B::foo()
이 될 것이고 이것이 호출 될 함수입니다.
일반적으로 컴파일러는 가상 메서드가있는 모든 개체에 올바른 함수를 가리키는 테이블이 있는지 확인해야하므로 프로그램에서 개체에 대해 가상 호출을 할 수 있습니다. 런타임에 객체와 관련된 테이블을 가져 와서 호출 할 올바른 메소드를 찾으십시오.
정적 및 동적 모드에서 위의 프로그램을 빌드하고 실행 한 다음 각 입력에 대해 얻은 결과를 관찰하십시오. 입력 및 결합 유형의 각 조합에 대해 얻은 결과를 아래 표에 채우십시오.
Binding | static dynamic
Input
-----
A ? ?
B ? ?
는 모든 경우에 출력은 동일한 x->foo()
메소드 호출의 평가에 의해 제조된다. 어떤 경우에 동적 인 바인딩이 있습니까? 동적 바인딩에 대한 위의 설명에 대한 이해와 일치합니까?
class Base {
public:
int Foo();
virtual int Bar();
};
class D1 : public Base {
public:
int Foo();
virtual int Bar();
};
class D2 : public Base {
public:
int Foo();
virtual int Bar();
};
main()
{
Base * b = (rand() < 100) ? new D1 : new D2;
// Always calls Base::Foo()
b->Foo();
// Call either D1::Bar() or D2::Bar()
b->Bar();
}
개체를 삭제하지 않았 으면 가상 소멸자가 없으므로 잘못되었을 수 있습니다. –
@NeilKirk 입력 해 주셔서 감사합니다.하지만 질문은 바인딩에 관한 것이 었으며 완전한 클래스를 작성하는 방법이 아닙니다. 클래스가 가지고 있어야하는 모든 메소드를 추가하면 대답이 명확하지 않게됩니다. –
나쁜 일이 일어나지 않도록 격려하는 "덜 명확한"대답을하는 것이 좋습니다. –
정적 및 동적 연결은 가상 및 비 가상 기능과 크게 직각을 이룹니다. –
@JonathanLeffler 그는 정적 대 동적 바인딩 *을 의미한다고 생각합니다. – 5gon12eder
@ 5gon12eder 연결과 바인딩간에 차이점이 있습니까? –