14

私の友人は、今日、私に次のチャレンジを送ってくれました。

次のコードを前提としてOBJECT_HAS_VTABLE、プログラムがを出力するようにの実装を提案しますAnObject has a vtable = 0, AnObjectWithVTable has a vtable = 1

class AnObject
{
    int m_a;
    void DoSomething() {}

public: 
    AnObject() {m_a = 0;}
};

class AnObjectWithVTable
{
    int m_b;
    virtual void DoStuff() { }

public: 
    AnObjectWithVTable() {m_b = 0;}
};

void main()
{
    printf("AnObject has a vtable = %i, AnObjectWithVTable has a vtable = %i\n",
           OBJECT_HAS_VTABLE(AnObject),
           OBJECT_HAS_VTABLE(AnObjectWithVTable));
}

私は私が十分にまともだと思う次の解決策を思いついた:

template <typename T>
bool objectHasVtable()
{
    class __derived : public T {};
    T t;
    __derived d;

    void *vptrT=*((void **)&t);
    void *vptrDerived=*((void **)&d);

    return vptrT != vptrDerived;
}

#define OBJECT_HAS_VTABLE(T) objectHasVtable<T>()

この問題に対するより良い解決策はありますか?

編集

ソリューションは、すべてのコンパイラで一般的である必要はありません。gcc、g ++、MSVCで動作します...ソリューションが有効であることがわかっているコンパイラを指定するだけです。鉱山はMSVC2010用です。

4

3 に答える 3

19

標準的な方法は、C ++ 11 / C ++ 03 TR1 / Boostを使用std::is_polymorphicして、クラス(およびそのベース)に仮想メンバーが含まれているかどうかを判別することです。

#include <type_traits>
#define OBJECT_HAS_VTABLE(T) (std::is_polymorphic<T>::value)
于 2011-05-11T20:47:18.163 に答える
11

完全を期すために、これが私の相棒がちょうど私に送った答えです。見た目からすると、おそらくTR1のやり方と似ています(私自身はコードを見ていませんが)。

template<class T>
class HasVTable
{
public :
    class Derived : public T
    {
        virtual void _force_the_vtable(){}
    };
    enum { Value = (sizeof(T) == sizeof(Derived)) };
};

#define OBJECT_HAS_VTABLE(type) HasVTable<type>::Value
于 2011-05-11T21:00:24.977 に答える
3

C++の次のプロパティを使用できます。

  1. dynamic_cast引数がポリモーフィッククラスでない場合、コンパイル時に失敗します。このような障害は、SFINAEで使用できます。
  2. dynamic_cast<void*>完全なポリモーピックオ​​ブジェクトのアドレスを返す有効なキャストです。

したがって、C ++ 11では:

#include <iostream>
#include <type_traits>

template<class T>
auto is_polymorphic2_test(T* p) -> decltype(dynamic_cast<void*>(p), std::true_type{});

template<class T>
auto is_polymorphic2_test(...) -> std::false_type;

template<class T>
using is_polymorphic2 = decltype(is_polymorphic2_test<T>(static_cast<T*>(0)));

struct A {};
struct B { virtual ~B(); };

int main() {
    std::cout << is_polymorphic2<A>::value << '\n'; // Outputs 0.
    std::cout << is_polymorphic2<B>::value << '\n'; // Outputs 1.
}
于 2020-01-27T20:32:39.173 に答える