如何初始化静态成员对象?

5

我没想到我不知道这个 :) 。还有一个类似的问题并没有帮助。

所以在这里提问。请考虑下面的类:

//in Agent.h
class Agent : public ns3::Object{
private:
//...

    static BaseWifi m_wifi;

//...
};

这是什么:

//Agent.cpp
BaseWifi temp;
BaseWifi Agent::m_wifi = temp;

与此非常不同:

//Agent.cpp
BaseWifi Agent::m_wifi = BaseWifi();

第二种方法对我不起作用。为什么?怎么办?
我不想给您更多代码的麻烦,因为我在程序深处遇到了这个问题。程序生成段错误,因为在“BaseWifi”的构造函数内部未正确初始化那些成员。当使用这些未初始化的内部成员时,会发生段错误。
提前感谢您的意见和回答。
附带说明: 事实上,当我尚未初始化此静态成员并删除额外行时,我发现了这个问题。
BaseWifi temp;

在我的 main() 函数中,这让我更加困惑!!!(这可能取决于我在 BaseWifi 的构造函数中放了什么,所以现在不要在意它)
更新-1: 对于那些想看看 BaseWifi 的人:
class BaseWifi {
    ns3::WifiHelper m_wifiHelper; // a wifi helper apply to setup vehicles Wifi

    ns3::NqosWifiMacHelper m_wifiMacHelper; // a wifi mac helper apply to setup vehicles Wifi

    ns3::YansWifiPhyHelper m_wifiPhyHelper; // a wifi phy helper apply to setup vehicles Wifi

    std::string m_phyMode;

    double m_rss;  // -dBm

    bool m_init_done;

public:

    BaseWifi();

    virtual void init();

    ns3::NetDeviceContainer Install(ns3::NodeContainer &c);

    virtual ~BaseWifi();
};

BaseWifi::BaseWifi() {
    m_init_done = false;
    m_rss = -80;
    m_phyMode ="DsssRate1Mbps";
    // TODO Auto-generated constructor stub
    init();
}

void BaseWifi::init() {
    NS_LOG_UNCOND("inside BaseWifi::init()");
      m_wifiHelper.SetStandard (ns3::WIFI_PHY_STANDARD_80211b);

      m_wifiPhyHelper =  ns3::YansWifiPhyHelper::Default ();

      // This is one parameter that matters when using FixedRssLossModel
      // set it to zero; otherwise, gain will be added
      m_wifiPhyHelper.Set ("RxGain", ns3::DoubleValue (0) );

      // ns-3 supports RadioTap and Prism tracing extensions for 802.11b
      m_wifiPhyHelper.SetPcapDataLinkType (ns3::YansWifiPhyHelper::DLT_IEEE802_11_RADIO);

      ns3::YansWifiChannelHelper wifiChannel;

      wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");

      // The below FixedRssLossModel will cause the rss to be fixed regardless
      // of the distance between the two stations, and the transmit power
      wifiChannel.AddPropagationLoss ("ns3::FixedRssLossModel","Rss",ns3::DoubleValue (m_rss));

      m_wifiPhyHelper.SetChannel (wifiChannel.Create ());

      // Add a non-QoS upper mac, and disable rate control
      m_wifiMacHelper = ns3::NqosWifiMacHelper::Default ();

      m_wifiHelper.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
                                    "DataMode",ns3::StringValue (m_phyMode),
                                    "ControlMode",ns3::StringValue (m_phyMode));
      // Set it to adhoc mode
      m_wifiMacHelper.SetType ("ns3::AdhocWifiMac");

      m_init_done = true;
}

//Install the class's embedded settings on the nodes in this node container.
ns3::NetDeviceContainer BaseWifi::Install(ns3::NodeContainer &nc) {
    return m_wifiHelper.Install(m_wifiPhyHelper, m_wifiMacHelper, nc);
}

2
@rahman "对我来说不起作用"的确切意思是什么? - jrok
1
如果您拥有指针或任何类型的复杂数据,您应该遵循三法则(Rule of Three) - Some programmer dude
1
如果您不提供复制构造函数并进行深拷贝,编译器将只生成浅拷贝,这意味着对于指针,仅拷贝指针而不是指向的内容。这意味着您将有多个指向相同数据的指针,如果一个对象删除了该数据,则其他指针现在将指向已删除的数据。 - Some programmer dude
@JoachimPileborg 我需要更深入地研究我在类中使用的成员类,并查看复制构造函数是否有帮助。我会回来告诉你这个结果。然而,我仍然困惑为什么在我的main()函数中的其他地方额外声明该类会阻止程序崩溃!? - rahman
@PeteBecker 这确实是真的。但是如果我不遵循“三写”规则并编写质量差的构造函数,我可能会陷入特殊情况。我想这就是我的实际问题。 - rahman
显示剩余6条评论
2个回答

8

我之前遇到过这种问题。显然,静态成员对象的初始化非常依赖于实现在代码中的位置以及(可能)整个编译的方式。我找到的解决方法(某处)是将整个内容包装成一个静态成员函数,像这样:

//in Agent.h
class Agent : public ns3::Object{
    private:
    //...

    static BaseWifi& m_wifi();
    //...
};

并且:

//in Agent.cpp
BaseWifi& Agent::m_wifi() {
    static BaseWifi TheObject=BaseWifi();
    return TheObject;
}

这样,当第一次调用静态成员函数时,对象就会被正确地初始化。


这是一个不错的“变通方法”,尽管在许多情况下,在C++中这样的变通方法是唯一的解决方案。谢谢。 - rahman
不过,我会尝试在我的问题下面评论的有关复制构造函数的建议,并明天回来告诉你们。 - rahman

0

这里的区别在于第一种方法使用复制构造函数来初始化对象,而第二种方法使用默认构造函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接