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);
}
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.
The difference here is the first approach is using copy constructor to initialize the object while the second is using the default constructor.
Related
I am working with a project that is largely not of my creation, but am tasked with adding in some functionality to it. Currently, there is a device class that has a member variable that is responsible for storing information about a storage location, setup like this:
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
StorageInfo.hpp
class StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
I am tasked with implementing a different storage option so that the two can be switched between. The information functions that this new storage option has would be the same as the initial storage option, but the implementation in retrieving that information is vastly different. In order to keep things clean and make it easier to maintain this application for years to come, they really need to be defined in two different files. However, this creates an issue inside of device.cpp, and in every single other file that calls the StorageInfo class. If I create two separate member variables, one for each type of storage, then not only will I need to insert a million different ifelse statements, but I have the potential to run into initialization issues in the constructors. What I would instead like to do is have one member variable that has the potential to hold either storage option class. Something like this:
StorageInfoA.hpp
class StorageInfoA: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
StorageInfoB.hpp
class StorageInfoB: StorageInfo {
public:
void initializeStorage();
void updateStorageInfo();
int popLocation();
int peakLocation();
uint16_t totalSize();
uint16_t remainingSize();
// More declarations here
private:
//Even more stuff here
}
device.hpp
class device {
public:
// Stuff
private:
// Stuff
StorageInfo storage_info_;
// Even more stuff
}
device.cpp
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = StorageInfoA();
} else {
storage_info_ = StorageInfoB();
}
// Then, these types of calls would return the correct implementation without further ifelse calls
storage_info_.updateStorageInfo();
However, I know that cpp absolutely hates anything with dynamic typing, so I don't really know how to implement this. Is this kind of thing even possible? If not, does anyone know of a similar way to implement this that does work with cpp's typing rules?
You are on the right track, but you have to learn how to use polymorphism. In your example, you need the following fixes:
In the base class, make all functions virtual, and add a virtual
destructor:
class StorageInfo {
public:
virtual ~StorageInfo(){}
virtual void initializeStorage();
//...
};
Make your inheritance public:
class StorageInfoA: public StorageInfo {
Instead of holding StorageInfo by value, hold it in a smart pointer:
class device {
private:
std::unique_ptr<StorageInfo> storage_info_;
};
device constructor will look like
//Somewhere in the constructor of device.cpp
if(save_to_cache){
storage_info_ = std::make_unique<StorageInfoA>();
} else {
storage_info_ = std::make_unique<StorageInfoB>();
}
Finally, you will use it like an ordinary pointer:
storage_info_->updateStorageInfo();
I've visited this forum many many many times, but this is my actual first post here. Usually I can find my answer here and I guess I've probably found it this time, but this time my knowledge is lacking to understand the solutions given (been learning C++ for the last 2 weeks).
The error I get:
no matching function for call to 'WidgetBridge::WidgetBridge()'
an extraction of my (rather lengthy) code:
class Room {
private:
//initializer list of internal objects
WidgetBridge bridge_thermostat;
WidgetBridge bridge_relay;
public:
//Constructor of the class:
Room() : bridge_thermostat(V100), bridge_relay(V107){}
void initBridges(String authThermostat, String authRelay){
bridge_thermostat.setAuthToken(authThermostat);
bridge_relay.setAuthToken(authRelay);
}
void receiveCurrentT(float param){
currentT = param;
Blynk.virtualWrite(V10, currentT);
timer.restartTimer(thermostatTimer ); //reset isDead timer for thermostat
Blynk.setProperty(V17, "color", BLYNK_GREEN); //change LED color
Blynk.virtualWrite(V17, 200);
}
} livingRoom;
BLYNK_CONNECTED() {
Blynk.syncAll();
livingRoom.initBridges("xxx", "xxxx"); //auth of: thermostat, relay
}
BLYNK_WRITE(V10){ livingRoom.receiveCurrentT(param.asFloat()); } //receive currentT from thermostat
Based on the answers I've found on this forum it appears that WidgetBridge doens't have its own constructor when called. Based on the answers given I've also tried:
public:
//Constructor of the class:
Room() : {
bridge_thermostat = V100;
bridge_relay = V107;
}
but that rendered the same error. I've continued reading about static fields, constructors, namespaces, etc. but bottomline: I'm stuck and I don't know how to fix this.
Additional info: code is for an esp8266 arduino wifi module which communicates with other esp8266's (relay and thermostat). The communication takes place through 'bridges' which are created using code from the Blynk app.
Thank you for your time!
UPDATE: I've finally found the actual calss widgetbridge itself. And from the mentioned solution I gathered that it has no constructor of itself, but it does..so now I'm really lost. Here's part of the widget class:
class WidgetBridge
: private BlynkWidgetBase
{
public:
WidgetBridge(uint8_t vPin)
: BlynkWidgetBase(vPin)
{}
void setAuthToken(const char* token) {
char mem[BLYNK_MAX_SENDBYTES];
BlynkParam cmd(mem, 0, sizeof(mem));
cmd.add(mPin);
cmd.add("i");
cmd.add(token);
Blynk.sendCmd(BLYNK_CMD_BRIDGE, 0, cmd.getBuffer(), cmd.getLength()-1);
}
(....)
};
From the code extract you posted (partial) and the error message(partial too...) , the only reasonable answer is that the WidgetBridge class as no default constructor (i.e. constructor with 0 argument).
Probably because the base class BlynkWidgetBase has no default constructor as well.
So you get compiler errors on those lines
//initializer list of internal objects
WidgetBridge bridge_thermostat;
WidgetBridge bridge_relay;
You can either implement a WidgetBride default constructor or instanciate those two variables with the constructor taking a uint8_t parameter :
//initializer list of internal objects
WidgetBridge bridge_thermostat(3);
WidgetBridge bridge_relay(4);
3 and 4 to be replaced by whatever value that makes sense, but only you can know that from the code extract
First of all, sorry for the title. I didn't know exactly how to give name to the situation I'm facing.
I am developing a project in C++ that will run over QNX (so answers that recur to Windows libraries are not good).
I have one class that holds and manipulates all my data, and a few other classes that are responsible for dealing with my UI.
The UI manipulating classes include my data class, and when they are initialized, they all get a pointer to the same data object (each one uses different parts of it, though). And the normal flow of the program is the UI receiving events from the user, and then making calls to the data class and updating itself, according to the data class replies. That all works just fine.
The problem is, sometimes it might happen that this data class object receives calls from other sorts of external events (let's say a call from a class responsible for communication), asking it to change some of it's values. After doing so, it would have to update the UI (thus, having to make a call to the UI classes).
The actual objects to all the classes (UI and data) are contained by the "main" class. But as the UI classes include the data class to be able to call it's methods, the data class including UI classes in order to be able to call their methods would fall into mutual inclusion.
The problem resumes, in a very simplistic way (I am just trying to give a visual example of the information flow), to something like this:
main.cpp
#include "interface.h"
#include "data.h"
Data data_;
Interface interface_;
// Initialize all data from files, etc
data_.Init();
// Call the interface that will use all of this data
interface_.Init(&data_);
while(1);
interface.h
#include "data.h"
class Interface
{
Data *data_;
void Init(Data *data);
void ReceiveEvent();
void ChangeScreen (int value);
};
interface.cpp
#include "interface.h"
void Interface::Init(Data *data)
{
// Get the pointer locally
data_ = data;
}
// Function called when a (for example) a touch screen input is triggered
void Interface::ReceiveEvent()
{
ChangeScreen(data_->IncreaseParam1());
}
void Interface::ChangeScreen (int value);
{
// Set the value on screen
}
data.h
class Data
{
int param 1;
void Init();
int IncreaseParam1();
void ReceiveExternalEvent();
};
**data.cpp"
#include "data.h"
void Data::Init()
{
// The value actually come from file, but this is enough for my example
param1 = 5;
}
int IncreaseParam1()
{
param1 += 5;
return param1;
}
// This is called from (for example) a communication class that has a
// pointer to the same object that the interface class object has
void ReceiveExternalEvent()
{
IncreaseParam1();
// NOW HERE IT WOULD HAVE TO CALL A METHOD TO UPDATE THE INTERFACE
// WITH THE NEW PARAM1 VALUE!
}
I hope I made myself clear enough.
Can someone please give me ideas on how to deal with this situation?
Thanks a lot in advance!
Both Data and Interface are singletons. You expect to only have one instance of each class in existence. So:
Class Data {
public:
static Data *instance;
Data()
{
instance=this;
}
// Everything else that goes into Data, etc...
};
Class Interface {
public:
static Interface *instance;
Interface()
{
instance=this;
}
// Everything else that goes into Data, etc...
};
Now, ReceiveExternalEvent() will simply invoke Data::instance->method() and/or Interface::instance->method(), and so on...
This is a classical singleton design pattern.
Also, you might find some additional Google food of likely interest to you: "model view controller" and "mvc".
I've developed a game on Cocos2d-x v2 platform
I started on Android, after completely finishing the coding on Eclipse I used the same code on Xcode to create and iOS version.
After adding all the required libraries, I succeeded in compiling the code. However, the game hangs the moment it runs on an iOS device, although it runs without any problem on Android.
I tried both the emulator and an iPod, but I always get an EXC_BAD_ACCESS when accessing a static member from a static method. The static member would always point to 0x0!!
Here's an excerpt from the code:\
AppDelegate.cpp
#include "AppDelegate.h"
#include "NASEncData.h"
AppDelegate::AppDelegate()
{
ep = NASEncData::sharedUserData();
}
NASEncData.h
namespace CocosNas
{
class NASEncData : public CCObject
{
public:
static NASEncData* sharedUserData();
private:
NASEncData();
static void initXMLFilePath();
static std::string m_sFilePath;
}
}
NASEncData.cpp
#include "NASEncData.h"
NASEncData* NASEncData::sharedUserData()
{
initXMLFilePath();
// only create xml file one time
// the file exists after the programe exit
if ((! isXMLFileExist()) && (! createXMLFile()))
{
return NULL;
}
if (! m_spUserData)
{
m_spUserData = new NASEncData();
}
return m_spUserData;
}
void NASEncData::initXMLFilePath()
{
if (! m_sbIsFilePathInitialized)
{
m_sFilePath += CCFileUtils::sharedFileUtils()->getWriteablePath() + NASENCDATA_XML_FILE_NAME; <----error happens here
m_sbIsFilePathInitialized = true;
}
}
Based on the comments on your question, your problem could be the initialization order of static data. To be more specific, I think it is possible that the static AppDelegate instance gets created and initialized before the static members in the NASEncData. And this problem could also explain the fact that you are seeing different behavior on different platform, because the initialization order of unrelated static data are compiler and linker dependent.
To fix this, you could change your NASEncData like this: (note that this is only one possible fix, although if the initialization order of statics is really your problem, I think this is the simplest and best solution, apart from redesigning your code so that you don't have to rely on static members.)
NASEncData.h
namespace CocosNas
{
class NASEncData : public CCObject
{
public:
static NASEncData* sharedUserData();
private:
NASEncData();
static void initXMLFilePath();
// Note how the stuff below this line have changed
struct StaticData
{
std::string m_sFilePath;
// Put other static members here
// (e.g. m_sbIsFilePathInitialized, m_spUserData, etc.)
// Put a proper constructor here if needed
};
static StaticData & getStaticData ()
{
static StaticData s_data;
return s_data;
}
}
}
NASEncData.cpp
void NASEncData::initXMLFilePath()
{
if (! m_sbIsFilePathInitialized)
{
// Note the change in accessing m_sFilePath
// You should access all your static members like this
getStaticData().m_sFilePath +=
CCFileUtils::sharedFileUtils()->getWriteablePath() +
NASENCDATA_XML_FILE_NAME;
getStaticData().m_sbIsFilePathInitialized = true;
}
}
What this does in ensure that when you try and access your static member data, they have already been initialized. This happens because all your static member data are now defined inside a function as static, and for accessing them you have to call that function, and the compiler generates code to make sure that the first time that function is invoked (and only the first time) your data is constructed and initialized properly, which in turn means that the first time you actually try to access this data, whenever and wherever that may be from, your data is properly initialized.
It was indeed an initialization problem I just had to move the code from the construction to bool AppDelegate::applicationDidFinishLaunching() and it worked!
Here is what i am trying to do.
I have Three Classes:
1) CEngine
2) CLogManager
3) CWindowGL
Ad1.
This class 'does' the tricky things to get the game engine going,
an application utilizing it, can call only few public members to
get the game going -
class CEngine
{
public:
CEngine();
~CEngine(); // should this go to private?
bool Init(width,height,...);
void Destroy();
void Run();
bool LoadMap(...);
private:
CLogManager *m_pLogManager;
CWindowGL *m_pWindowManager
}
// Example usage
CEngine *Engine=new CEngine;
Engine->Initialize(...)
Engine->LoadMap(...)
Engine->Run()
Engine->Destroy()
delete(Engine)
Ad2.
This class controls the logging facility
it just allows me to dump some log into the log data file:
class CLogManager
{
public:
CLogManager();
~CLogManager();
void Write(const char *fmt,...);
private:
FILE *fp;
std::string m_sFileName; // unique filename generated at the constructor
SYSTEMTIME m_tSystemTime;
}
Ad3.
This class handles the window creation, and pixel format settings,
and few other things related to the window itself - nothing else,
but it also needs to utilize CLogManager - to dump few informations
for debug purposes.
Now the question is:
When a CLogManager constructor is called, class generates a unique filename that is:
m_sFileName="data/logs/enginelog_%i%i%i.txt"; // hour, minute, second
CEngine class in the Init method does:
m_pLogManager = new CLogManager;
and later on it uses it with m_pLogManager->Write(....) to log events.
That's ok for CEngine, but i would like to use the same functionality
in CWindowGL class and here is the question.
I would like my code to share CLogManager across :
CEngine
CWindowGL
...
...
...
and few others that i'll implement.
I can't do this by adding "Instance()" type of method like:
static CLogManager &Instance()
{
static CLogManager s_instance;
return s_instance;
}
and calling:
CLogManager::Instance().Write(" LOG MESSAGE ");
As this would cause my CLogManager to generate new filename each time when a
constructor is called.
Do i have to
extern CEngine *Engine;
somewhere to call
Engine->Log(" LOG MESSAGE ")
wrapper everytime or there is something else i can stick to?
I know it is more like a 'code-design' question, but i would like to see
how do you guys handle such things.
Normally i would do this with extern, but that would require me to check
m_pLogManager!=NULL within a wrapper function to a private member - and just
don't know if that's OK.
Maybe there's some other - better approach?
I will be adding few other classes like. TexturesManager - and would like this class to
store the actual size of textures loaded and so on, so this would also require me to
not to call Instance() to class each time the texture is called - as this would create/destruct the class without storing the needed size / array of textures already loaded...
Uff..
Thanks, hope this is clear.
I can't do this by adding "Instance()" type of method as this would cause my CLogManager to generate new filename each time when a constructor is called.
Actually no, the constructor would be called only once during your program lifetime. The singleton pattern is what you most likely want for your logging class.
What you'll generally find in these situations is a static set of methods that use a singleton underneath. All consumers call the static method which returns the one, single, instance of your logger, which you then call methods on.