我一直在寻找Visitor
模式的替代方案,以映射类层次结构中类型的行为,并允许多次调度。每次向类层次结构添加新类型时,都必须更新所有支持访问者。所以我遇到std::type_index
,根据cppreference.com可能会做到这一点。然后我想,现在我必须为每个子类实现get_type_index
,这与访问者模式的accept
方法有关。这只是工作的一半
必须为Visitor
模式完成。但后来我发现,显然你只需要在基类中实现一个(非纯)虚函数来使整个事情发挥作用。以下是我的code,我有以下问题:
BaseVirtual
?#include <iostream>
#include <map>
#include <memory>
#include <string>
#include <typeindex>
struct Base
{
std::type_index get_type_index( ) const
{
return std::type_index( typeid(*this) );
}
};
struct BaseVirtual
{
virtual std::type_index get_type_index( ) const
{
return std::type_index( typeid(*this) );
}
};
template<typename BaseType>
struct A : public BaseType
{
};
template<typename BaseType>
struct B : public BaseType
{
};
template<typename BaseType>
struct C : public BaseType
{
};
int main( int argc,
char **argv )
{
std::map<std::type_index, std::string> typeToStringMap = { { std::type_index( typeid(Base) ), "Base" }, { std::type_index( typeid(A<Base> ) ), "ABase" }, { std::type_index( typeid(B<Base> ) ), "BBase" }, { std::type_index( typeid(C<Base> ) ), "CBase" }, { std::type_index( typeid(BaseVirtual) ),
"BaseVirtual" }, { std::type_index( typeid(A<BaseVirtual> ) ), "ABaseVirtual" }, { std::type_index( typeid(B<BaseVirtual> ) ), "BBaseVirtual" }, { std::type_index( typeid(C<BaseVirtual> ) ), "CBaseVirtual" } };
A<Base> a;
B<Base> b;
C<Base> c;
A<BaseVirtual> av;
B<BaseVirtual> bv;
C<BaseVirtual> cv;
auto asp = std::make_shared<A<Base>>( );
auto bsp = std::make_shared<B<Base>>( );
auto csp = std::make_shared<C<Base>>( );
auto avsp = std::make_shared<A<BaseVirtual>>( );
auto bvsp = std::make_shared<B<BaseVirtual>>( );
auto cvsp = std::make_shared<C<BaseVirtual>>( );
A<Base>* ap = new A<Base>;
B<Base>* bp = new B<Base>;
C<Base>* cp = new C<Base>;
A<BaseVirtual>* avp = new A<BaseVirtual>;
B<BaseVirtual>* bvp = new B<BaseVirtual>;
C<BaseVirtual>* cvp = new C<BaseVirtual>;
std::cout << typeToStringMap[a.get_type_index( )] << std::endl;
std::cout << typeToStringMap[b.get_type_index( )] << std::endl;
std::cout << typeToStringMap[c.get_type_index( )] << std::endl;
std::cout << typeToStringMap[av.get_type_index( )] << std::endl;
std::cout << typeToStringMap[bv.get_type_index( )] << std::endl;
std::cout << typeToStringMap[cv.get_type_index( )] << std::endl;
std::cout << typeToStringMap[asp->get_type_index( )] << std::endl;
std::cout << typeToStringMap[bsp->get_type_index( )] << std::endl;
std::cout << typeToStringMap[csp->get_type_index( )] << std::endl;
std::cout << typeToStringMap[avsp->get_type_index( )] << std::endl;
std::cout << typeToStringMap[bvsp->get_type_index( )] << std::endl;
std::cout << typeToStringMap[cvsp->get_type_index( )] << std::endl;
std::cout << typeToStringMap[ap->get_type_index( )] << std::endl;
std::cout << typeToStringMap[bp->get_type_index( )] << std::endl;
std::cout << typeToStringMap[cp->get_type_index( )] << std::endl;
std::cout << typeToStringMap[avp->get_type_index( )] << std::endl;
std::cout << typeToStringMap[bvp->get_type_index( )] << std::endl;
std::cout << typeToStringMap[cvp->get_type_index( )] << std::endl;
}
输出:
Base
Base
Base
ABaseVirtual
BBaseVirtual
CBaseVirtual
Base
Base
Base
ABaseVirtual
BBaseVirtual
CBaseVirtual
Base
Base
Base
ABaseVirtual
BBaseVirtual
CBaseVirtual
答案 0 :(得分:1)
为什么类型正确地映射到继承自
的类BaseVirtual
因为C ++标准说他们应该:
[expr.typeid] / 2 当
typeid
应用于类型为多态类类型(10.3)的glvalue表达式时,结果引用std::type_info
表示glvalue引用的最派生对象(1.8)(即动态类型)类型的对象。
编译器是如何做到的,它有多贵?
无关的实施细节。一种方法是向vtable添加指向type_info
或类似事物的指针。
可携带吗?
是的。同样,您观察到的行为是C ++标准规定的。