How to initialize a static member object?
Asked Answered
P

3

5

I didn't know that I didn't know this :) . and a similar question here didn't help much.

So here i am asking. Please Consider the following class:

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

    static BaseWifi m_wifi;

//...
};

is this :

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

very much different from this:

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

The second approach doesn't work for me. why and how?

I don't want to trouble you with more codes coz I faced this problem deep in my program. The program generate seg faults as things(members) inside BaseWifi's constructor are not initialized correctly. when those uninitialized internal members are used, seg faults occur.

Thank you in advance for your kind comments and answers.

p.s.: In fact I found this issue when I hadn't yet initialized this static member and I was deleting an extra line :

BaseWifi temp;

in my main(), which added more to my confusion!!!(this one could be dependent on what I put in BaseWifi's constructor, so dont mind it for now)

Update-1: For those who would like to see the 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);
}
Popple answered 13/8, 2013 at 11:38 Comment(11)
@Popple What does "doesn't work for me" mean, exactly?Ashworth
For the second aprproach, do you get compilation errors? Mind telling us what those errors are in that case? Because normally that would be fine.Mcmichael
@JoachimPileborg no compilation error. it generate seg faults as things(members) inside BaseWifi's constructor are not initialized correctly. when those internal members are used, seg faults occur.Popple
Maybe a problem with copy-construction? Is the BaseWifi class yours? If so, you do have a copy-constructor? Maybe you should try to fix those segmentation faults, as they might crop up somewhere else?Mcmichael
@JoachimPileborg yes the class is mine. but, no I don't have a copy constructor. Are you guessing a copy constructor can solve the issue?Popple
If you have pointers, or really any kind of complex data, you should follow the rule of three.Mcmichael
can you show us BaseWifi code?Holcombe
If you don't provide a copy-constructor and does a deep copy, the compiler will generate only shallow copying, which means that for pointers only the pointers will be copied and not what they point to. That means that you then have multiple pointers pointing to the same data, and if one object then deletes that data the other pointers will now point to deleted data.Mcmichael
@JoachimPileborg I have to look more into the classes which i used as members in my class and see if a copy constructor would help. I will get back to you on this. However, I am still confused why an extra declaration of the class somewhere else in my main() stopped my program to crash!??Popple
At the risk of responding to a simplification that was made for this example, the simplest form of this initialization is BaseWifi Agent::m_wifi;.Cene
@PeteBecker this is really true. But I guess I can get caught in special circumstances if I don't follow the rule of three and write poor constructor. I guess This was my actual problem.Popple
F
8

I have run into these kind of issues before. Apparently the initialization of static member objects very much depends on where the implementation is done in your code and (probably) on how the whole thing is compiled. The solution that I found (somewhere) to the problem was to wrap the whole thing into a static member function like this:

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

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

and:

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

This way the object is initialized properly the first time the static member function is called.

Fortunio answered 13/8, 2013 at 11:56 Comment(2)
This is a nice "workaround", though in many instances in C++ such workarounds are the only SOLUTION. ThanksPopple
Still, I will try the suggestions commented below my question regarding copy constructors and will get back to you guys tomorrow.Popple
R
0

The difference here is the first approach is using copy constructor to initialize the object while the second is using the default constructor.

Riggall answered 13/8, 2013 at 13:1 Comment(0)
I
0

Since C++11 a static member can be declared and initialized inside a class with the inline keyword.

Class X
{
    inline static int n = 1;
};

This is both a declaration and a definition with initialization.

Impetus answered 25/1 at 15:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.