Использование __ declspec (novtable) на абстрактных базовых классах влияют на RTTI всегда?

Некоторые люди предлагают определенные плагины и/или браузеры. Я был бы, не потому что они [только 110] действительно полезны для той одной платформы; тестовый прогон на Firefox не переведет точно в IE7. Рассмотрение 99,999999% сайтов имеет больше чем один браузер, посещает их, необходимо проверить производительность на всех популярных платформах.

Мое предложение должно было бы сохранить это в JS. Создайте страницу сравнительного тестирования со всем своим тестом JS на и время выполнением. У Вас мог даже быть он сообщение AJAX результаты назад Вам для хранения его полностью автоматизированным.

Тогда просто промывка и повторение по различным платформам.

11
задан paxos1977 26 November 2009 в 02:33
поделиться

1 ответ

MSCV использует один vptr на объект и один vtbl на каждый class для реализации механизма OO, такого как RTTI и виртуальные функции.
Таким образом, 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) );

B должен быть абстрактным классом при использовании __ declspec (novtable) .
Экземпляра B не будет, кроме конструктора D1.
И __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 чистой виртуальной функцией , а B - абстрактным классом.
определение чистой виртуальной функции могло (не должно ) отсутствовать.
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 не определен во время построения. Это одна из причин, по которой вызов виртуальной функции в конструкторе не рекомендуется.

Если vptr в D2 :: D2 () был B и определение B :: f () отсутствовало, this-> f (); выйдет из строя при разыменовании указателя на функцию в vtbl.
Если vptr в D2 :: D2 () был B, а B использует novtable, this-> f (); выйдет из строя при разыменовании неинициализированного vptr.

Фактически, vptr в D2 :: D2 ( ) является D2 в MSVC (msvc8). Компилятор установил vptr на D2 перед выполнением другого кода в D2 :: D2 ().
Итак, this-> f (); вызывает D2 :: f (), и три утверждения будут нарушены.

10
ответ дан 3 December 2019 в 08:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: