ns3中可以根据对象中的TypeId进行一个对象的创建。每一个对象的cc文件都有这样一个宏NS_OBJECT_ENSURE_REGISTERED,对对象进行注册。这个宏的内容:
#define NS_OBJECT_ENSURE_REGISTERED(type) \
static struct X ## type ## RegistrationClass \
{ \
X ## type ## RegistrationClass () { \
ns3::TypeId tid = type::GetTypeId (); \
tid.GetParent (); \
} \
} x_ ## type ## RegistrationVariable
type::GetTypeId (); 执行每个类中实现的静态函数GetTypeId ()。以PacketSink这个Application为例,其GetTypeId函数:
TypeId
PacketSink::GetTypeId (void)
{
static TypeId tid = TypeId ("ns3::PacketSink")
.SetParent<Application> ()
.AddConstructor<PacketSink> ()
.AddAttribute ("Local", "The Address on which to Bind the rx socket.",
AddressValue (),
MakeAddressAccessor (&PacketSink::m_local),
MakeAddressChecker ())
.AddAttribute ("Protocol", "The type id of the protocol to use for the rx socket.",
TypeIdValue (UdpSocketFactory::GetTypeId ()),
MakeTypeIdAccessor (&PacketSink::m_tid),
MakeTypeIdChecker ())
.AddTraceSource ("Rx", "A packet has been received",
MakeTraceSourceAccessor (&PacketSink::m_rxTrace))
;
return tid;
}
AddConstructor<PacketSink>
为对象类型注册构造器。这样就将一个类的TypeID与类的实例化关联到一起。
TypeId::AddConstructor (void)
{
struct Maker {
static ObjectBase * Create () {
ObjectBase * base = new T ();
return base;
}
};
Callback<ObjectBase *> cb = MakeCallback (&Maker::Create);
DoAddConstructor (cb);
return *this;
}
所以我看到PacketSinkHelper向ObjectFactory设置的是ns3::PacketSink的TypeID。
PacketSinkHelper::PacketSinkHelper (std::string protocol, Address address)
{
m_factory.SetTypeId ("ns3::PacketSink");
m_factory.Set ("Protocol", StringValue (protocol));//PacketSink中的属性
m_factory.Set ("Local", AddressValue (address));
}
表面上看到PacketSinkHelper中实例化的是Application,但是由于之前注册了ns3::PacketSink的TypeID,因此最终实例化的是PacketSink这个子类。
Ptr<Application> app = m_factory.Create<Application>