또는 __declspec (novtable)을 사용하여 알려진 다른 부정적인 영향이 있습니까? 어떤 문제에 대한 언급도 찾을 수없는 것 같습니다.추상 기본 클래스에서 __declspec (novtable)을 사용하면 어떤 방식 으로든 RTTI에 영향을 줍니까?
답변
MSCV는 one vptr per object and one vtbl per class
을 사용하여 RTTI 및 가상 함수와 같은 OO 메커니즘을 구현합니다.
RTTI와 가상 함수는 vptr이 올바르게 설정된 경우에만 제대로 작동합니다.
struct __declspec(novtable) B {
virtual void f() = 0;
};
struct D1 : B {
D1() {
} // after the construction of D1, vptr will be set to vtbl of D1.
};
D1 d1; // after d has been fully constructed, vptr is correct.
B& b = d1; // so virtual functions and RTTI will work.
b.f(); // calls D1::f();
assert(dynamic_cast<D1*>(&b));
assert(typeid(b) == typeid(D1));
__declspec(novtable)
을 사용할 때 B는 추상 클래스 여야합니다.
D1의 생성자를 제외하고는 B의 인스턴스가 없습니다.
그리고 __declspec (novtable)에는 대부분의 경우 부정적인 영향이 없습니다.
그러나 파생 클래스 __declspec(novtable)
의 건설 중에는 ISO C++ 의미와 달라집니다.
struct D2 : B {
D2() { // when enter the constructor of D2 \
// the vtpr must be set to vptr of B \
// if B didn't use __declspec(novtable).
// virtual functions and RTTI will also work.
this->f(); // should calls B::f();
assert(typeid(*this) == typeid(B));
assert(!dynamic_cast<D2*>(this));
assert(dynamic_cast<B*>(this));
// but __declspec(novtable) will stop the compiler \
// from generating code to initialize the vptr.
// so the code above will crash because of uninitialized vptr.
}
};
참고 : virtual f() = 0
; f를 pure virtual function
으로, B를 추상 클래스로 만듭니다.
순수 가상 함수 could
(must
)의 definition
이 누락되었습니다.
C++에서는 권장하지 않는 생성자에서 가상 함수 호출을 허용합니다.
업데이트 : D2의 실수 : 파생 생성자의 vptr.
struct D3 : B { // ISO C++ semantic
D3() { // vptr must be set to vtbl of B before enter
} // vptr must be set to vtbl of D2 after leave
};
그러나 vptr은 생성 중에 불확정합니다. 이것은 생성자에서 가상 함수 호출이 권장되지 않는 이유 중 하나입니다.
D2 :: D2()의 vptr이 B이고 v :: b (f)의 정의가 누락 된 경우 vtbl의 포인터를 함수로 역 참조 할 때 this->f();
이 충돌합니다.
D2 :: D2()의 vptr이 B이고 B가 novtable을 사용하는 경우 초기화되지 않은 vptr을 참조 해제 할 때 this->f();
이 중단됩니다.
실제로 D2 :: D2()의 vptr은 MSVC (msvc8)의 D2입니다. 컴파일러는 D2 :: D2()에서 다른 코드를 실행하기 전에 vptr을 D2로 설정합니다.
따라서 this->f();
은 D2 :: f()를 호출하며 3 개의 어설 션은 위반됩니다.
기본적으로 이것은 (1) 생성자에서 가상 함수 호출이없고 (2) 순수 가상 함수가 실제로 호출되면 더 이상 "순수 가상 함수 호출"이라는 오류 정보를 얻지 않습니다. – paxos1977
정확하게 이해하면 ctor 또는 dtor 내의 가상 fn 호출은 컴파일 타임 링크로 변환됩니다. (c/d) tors에서 가상 fn 호출을 할 수 없습니다. 그 이유는 기본 클래스의 객체가 생성 될 때 파생 된 클래스에 대한 지식이 없으므로 파생 클래스를 호출 할 수 없으며 같은 논리가 적용되는 dtors를 사용할 수 없기 때문입니다.
또한 관련 질문을 참조하십시오. http://stackoverflow.com/questions/1787752/ – paxos1977