Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'm a beginner to C++ and I was wondering if there was a good way to access a member of another object.
Currently I'm using this to access the members:
&_HeatSensor->IsOverheating == true;
&_LeftLegSensor->IsStalled == true;
/*... many more similar ones but different names*/
Where HeatSensor or LeftLegSensor is the name of the object and IsOverheating or IsStalled is a Boolean member in the object.
I want to create a new SensorOverLimit class, and create many objects(ex: Left Leg, MotorTemperature... etc.
To save time and reuse code, I want to be able to pass something that can reference the Boolean members that were created in the constructor and then save the location via reference or pointer as a member in the new SensorOverLimit object.
SensorOverLimit.cpp
SensorOverLimit::SensorOverLimit(bool* SensorAddress)
{
bool* Sensor = SensorAddress;
}
SensorOverLimit::Check()
{
if (SensorAddress == true)
{
somefunction();
}
}
main.cpp:
SensorOverLimit Overheating = new SensorOverLimit(bool* &_HeatSensor->IsOverheating);
SensorOverLimit DamagedLeg = new SensorOverLimit(bool* &_LeftLegSensor->IsStalled);
This doesn't work, does anyone have any ideas for how to get this to work?
Edit: Changed question, new answer...
SensorOverLimit.h:
class SensorOverLimit
{
bool* sensor;
public:
SensorOverLimit(bool* sensorAddress);
void check();
};
SensorOverLimit.cpp:
SensorOverLimit::SensorOverLimit(bool* sensorAddress)
: sensor(sensorAddress)
{
}
void SensorOverLimit::check()
{
if(*sensor)
{
somefunction();
}
}
Have a look at Remy's answer for references instead of pointers (bool& instead of bool*, and you can omit dereferencing (if(sensor))
main.cpp:
HeatSensor heatSensor;
LeftLegSensor leftLegSensor;
SensorOverLimit overHeating(&heatSensor.isOverheating);
SensorOverLimit leftLegDamaged(&leftLegSensor.isStalled);
int main(int, char*[])
{
// ...
return 0;
}
You might have noticed: I directly instantiated global variables. This is often more appropriate in embedded environments, at least easier to use.
Be careful with identifiers starting with an underscore - these are reserved in many cases (C++ standard, 2.10):
Each identifier that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use.
Each identifier that begins with an underscore is reserved to the implementation for use as a name in the global namespace.
Edit 2:
I'm coming up with a completely different design, inverting what you had so far:
class Sensor
{
public:
Sensor()
: isActive(false)
{ }
virtual ~Sensor()
{ }
void check()
{
if(getValue() != isActive)
{
isActive = !isActive;
if(isActive)
{
someFunction();
}
}
}
private:
bool isActive;
virtual bool getValue() = 0;
};
class HeatSensor : public Sensor
{
virtual bool getValue()
{
bool isActive = false;
// do what ever is necessary to detect overheat
// e. g. read from ADC and compare against threshold
return isActive;
}
};
class LegSensor : public Sensor
{
bool isSignal;
virtual bool getValue()
{
// do what ever is necessary to detect stalled leg
// e. g.: simply returning the value that has been set from
// within an interrupt handler
return isSignal;
}
};
Not really happy about the names of my members, you might find something better...
What is your intention of this design, however? Are you going to iterate over each city, checking the bool pointers? Seems a questionable design to me...
I suggest an alternative for you:
Each Sensor gets a SensorOverLimit* pointer, you might call it 'controller' or whatever seems appropriate to you. Then add functions to each Sensor class: oveheating(), stalling(), etc. Within these functions, you call a newly defined function of SensorOverLimit: disturb(int reason, Sensor* source). Instead of int, you could define an enum containing all possible reasons, such as Overheat, Stall, etc.
Could look like this:
class Sensor;
class SensorOverLimit
{
// appropriate members
public:
enum Disturbance
{
Overheat,
Stall,
};
SensorOverLimit() {}
void disturb(Disturbance reason, Sensor* source)
{
someFunction();
}
};
class Sensor
{
protected:
SensorOverLimit* controller;
public:
// ctor, getters, setters as needed
Sensor(SensorOverLimit* aController) : controller(aController) {}
};
class HeatSensor : public Sensor
{
public:
// ctor, getters, setters as needed
HeatSensor(SensorOverLimit* aController) : Sensor(aController) {}
void overheating()
{
if (controller)
controller->disturb(SensorOverLimit::Overheat, this);
}
};
class LegSensor : public Sensor
{
public:
// ctor, getters, setters as needed
LegSensor(SensorOverLimit* aController) : Sensor(aController) {}
void stalling()
{
if (controller)
controller->disturb(SensorOverLimit::Stall, this);
}
};
SensorOverLimit controller;
HeatSensor heatSensor(&controller);
LegSensor leftLegSensor(&controller);
int main(int, char*[])
{
// ...
heatSensor.overheating();
//...
leftLegSensor.stalling();
//...
return 0;
}
Advantage: You can associate many sensors to one and the same controller.
You can use a bool* pointer like this:
class SensorOverLimit
{
public:
bool* Sensor;
SensorOverLimit(bool* SensorAddress);
void Check();
};
...
SensorOverLimit::SensorOverLimit(bool* SensorAddress)
: Sensor(SensorAddress)
{
Check();
}
void SensorOverLimit::Check()
{
if (*Sensor)
{
somefunction();
}
}
SensorOverLimit *Overheating = new SensorOverLimit(&(_HeatSensor->IsOverheating));
SensorOverLimit *DamagedLeg = new SensorOverLimit(&(_LeftLegSensor->IsStalled));
...
Then you can do this:
_HeatSensor->IsOverheating = true;
...
Overheating->Check();
_LeftLegSensor->IsStalled = true;
...
DamagedLeg->Check();
With that said, it would be safer to use references instead of pointers:
class SensorOverLimit
{
public:
bool& Sensor;
SensorOverLimit(bool& SensorAddress);
void Check();
};
...
SensorOverLimit::SensorOverLimit(bool& SensorAddress)
: Sensor(SensorAddress)
{
Check();
}
void SensorOverLimit::Check()
{
if (Sensor)
{
somefunction();
}
}
SensorOverLimit *Overheating = new SensorOverLimit(_HeatSensor->IsOverheating);
SensorOverLimit *DamagedLeg = new SensorOverLimit(_LeftLegSensor->IsStalled);
...
_HeatSensor->IsOverheating = true;
...
Overheating->Check();
_LeftLegSensor->IsStalled = true;
...
DamagedLeg->Check();
Is there a particular reason why you're not using getters and setters in order to access the members of your objects?
If you're referencing to all your objects as pointers, you may want to reconsider that practice. This StackOverflow question gives some insight into common practice with C++ and pointers: Why should I use a pointer rather than the object itself?
I think the best answer to your question would actually be to familiarize yourself with the concept of pointers. This question as well the one I mentioned earlier give a good starting point - C++ Objects: When should I use pointer or reference. I think one of the best things to note is that if you are coming from a Java background, pointers and references are hidden in the code for you. Every object is a pointer and vice versa in Java. In C++, they are separate.
I think your desire to reuse code is commendable, but in this case, using pointers will probably cause unknown errors!
I'd recommend changing your constructor in the City class to actually work with the objects, not just their members (for instance, create a City with a person as your parameter, not whether the person is alive or dead). With a little more practice in object-oriented programming, you may find that it is much easier than your initial approach!
Related
I am using a simple inheritance structure to try and simplify code structure and reduce common code usage across a number of classes.
The idea is to allow a simple linked list structure within the class to allow the entire set of instances to be iterated.
EDIT:
To elaborate, this is intended to support a bunch of classes that can be aggregated by type and then iterated by type. Hence the decision to use a linked list with a static "first member" held in the class.
The actual application is support classes for switches, buttons, lights, parsers inside an embedded platform (Arduino).
When I create 20 switch instances of cSwitch (for instance)
cSwitch cSwitchA(_pin,callback);
cSwitch cSwitchB(_pin,callback);
I can then use
loop() {
cSwitch::checkAll();
}
inside my "loop" function, rather than having to do:
void loop() {
cSwitchA::check();
cSwitchB::check();
...
}
...
extending this to other classes, I can do:
loop() {
cSwitch::checkAll();
cLight::checkAll();
cParser::checkAll();
}
all of the members are declared with pins, parameters and callback functions.
I think that the problem is not specific to Arduino, but a little more abstract in that it could probably arise in any similar scenario.
class cGroup {
public:
cGroup(){cGroup::register_instance(this);}
~cGroup();
static void register_instance(cGroup * _inst) {
cGroup pInstance=nullptr;
if (_inst->getFirstInstance()==nullptr) {
_inst->setFirstInstance(_inst);
return;
} else {
pInstance=_inst->getFirstInstance();
}
while (1) {
if (pInstance->getNextInstance() == nullptr) {
pInstance->setNextInstance(_inst);
return;
} else {
pInstance=_inst->getNextInstance();
}
}
}
static void checkAll(cGroup * firstInstance);
virtual cGroup* getFirstInstance()=0;
virtual void setFirstInstance(cGroup*)=0;
};
class cMemberA: public cGroup {
public:
cMemberA():cGroup(){}
static void checkAll() {cGroup::checkAll(cMemberA::firstInstance);}
static cGroup * _firstInstance;
cGroup* getFirstInstance() {return cMemberA::firstInstance;}
void setFirstInstance(cGroup* _firstInstance){cMemberA::firstInstance = _firstInstance;}
};
cGroup * cMemberA::_firstInstance = nullptr;
class cMemberB: public cGroup {
... etc
};
The main need to do it this way stems from the fact that if I push the static "firstInstance" variable up into the cGroup class, it only allows for one long list containing many different types of Member classes. What I want is one list per type of Member class, meaning that I need to scope the static "firstInstance" variable into the Member class itself.
The problem I am finding is that I am going around in circles trying to figure out how to invoke getFirstInstance() and setFirstInstance from within the member class while only having a cGroup* pointer to play with.
If I have pure virtual classes inside of cGroup with cGroup * declarations, then these are not satisfied by declarations in the subclass of cMemberA * (and cMemberB *, cMemberC etc...)
declaring the "first-instance" members as "cMemberA*" leads to compilation issues (abstract class), but declaring them as cGroup* leads to an inability to invoke the required members in the cMemberA instances.
Is there another way to do this, or am I fundamentally going about this the wrong way? Please be gentle, it's been about 10 years since my last rodeo with C++ and I'm not a professional programmer.
Of course I can get around this issue by dispensing with cGroup entirely and just putting everything into cMemberA, cMemberB etc. but then that's where I was last week and as far as I recall, that's not the best way with C++ as the whole idea is to reduce code duplication.
The code you posted does have a problem, but I think it's different from the ones you mentioned.
The problem I see is that you call register_instance from the cGroup constructor, and then call virtual functions, eg. getFirstInstance() from that. Virtual calls don't work as expected at construction time (because the vtable isn't properly initialized yet). Basically you need to construct your object first, and you can call register once the object is fully constructed, in a second step.
The usual way around this would be to use a factory function instead of directly the constructors. The factory function would first create a new instance, then register that fully created instance, then return it. BUT, your factory function would need to create the instance on heap and return a pointer (if it returned by value, then it would register an instance, return a copy of it, then destruct the registered instance). Usually this isn't a problem, types with virtual functions are usually used as reference types (not value types) anyway, but in your particular embedded case that may be a problem.
Another way is to create intermediate classes between cGroup and cMemberX, eg. cMemberA: cMemberABase: cGroup. first_instance and getFirstIntsnace() etc. would be defined in cMemberABase. Then cMemberA's constructor could call cGroup::register, because by that time the vtable for cMemberABase is already constructed (but not yet for cMemberA!). In other words, when in the subclass constructor, the base subobject's virtuals can already be used, but not the virtuals defined in the subclass.
class cGroup {
protected:
cGroup(){}
public:
template <class G> static G* make() {
G* instance = new G();
cGroup::register_instance(instance);
return instance;
}
~cGroup() {}
static void register_instance(cGroup * _inst) {
cGroup* pInstance=nullptr;
if (_inst->getFirstInstance()==nullptr) {
_inst->setFirstInstance(_inst);
return;
} else {
pInstance=_inst->getFirstInstance();
}
while (1) {
if (pInstance->getNextInstance() == nullptr) {
pInstance->setNextInstance(_inst);
return;
} else {
pInstance=_inst->getNextInstance();
}
}
}
static void checkAll(cGroup * firstInstance) {
}
virtual cGroup* getFirstInstance()=0;
virtual void setFirstInstance(cGroup*)=0;
cGroup* getNextInstance() { return nextInstance; }
void setNextInstance(cGroup* nextInstance) { this->nextInstance = nextInstance; }
cGroup* nextInstance = nullptr;
};
class cMemberABase: public cGroup {
protected:
friend class cGroup;
cMemberABase():cGroup(){}
public:
static void checkAll() {cGroup::checkAll(cMemberABase::firstInstance);}
static cGroup * firstInstance;
cGroup* getFirstInstance() {return cMemberABase::firstInstance;}
void setFirstInstance(cGroup* _firstInstance){cMemberABase::firstInstance = _firstInstance;}
};
cGroup* cMemberABase::firstInstance = nullptr;
class cMemberBBase: public cGroup {
protected:
friend class cGroup;
cMemberBBase():cGroup(){}
public:
static void checkAll() {cGroup::checkAll(cMemberBBase::firstInstance);}
static cGroup * firstInstance;
cGroup* getFirstInstance() {return cMemberBBase::firstInstance;}
void setFirstInstance(cGroup* _firstInstance){cMemberBBase::firstInstance = _firstInstance;}
};
cGroup* cMemberBBase::firstInstance = nullptr;
class cMemberA: cMemberABase {
public:
cMemberA(): cMemberABase() {
cGroup::register_instance(this);
}
};
class cMemberB: cMemberBBase {
public:
cMemberB(): cMemberBBase() {
cGroup::register_instance(this);
}
};
It is much simpler and idiomatic to let the outer code organize objects into containers as needed:
cSwitch cSwitches[2] = {{_pin,callback}, {_pin,callback}};
loop() {
for (auto& switch : cSwitches)
switch.check();
}
If you want "names" for the elements, add an enum:
enum cSwitchNames { A, B, count };
cSwitches[A].check(); // if you need to check just one
Hello guys a have a problem, that i can't access field tablica[i]->help, in generuj function, its saying that this field is not existing in class Task.
How can i achieve it ?
class Task
{
protected:
string contents;
int id_pyt;
int nr_pyt;
};
class Task4Answ : public Task
{
private:
int help;
public:
Task4Answ(string contents1, int id,int nr,int help1)
{
contents=contents1;
id_pyt=id;
nr_pyt=nr;
help=help1;
}
};
class TaskCollection
{
protected:
Task *collection[60];
public:
friend class Generator;
TaskCollection()
{
collection[0] = new Task4Answ("Ile jest por roku w Polsce? \na) 1 \nb) 2 \nc) 3 \nd) 4",1,0);
collection[1] = new Task4Answ("Kto wygral tegoroczny Roland Garros? \na) Federer \nb) Djokovic \nc) Nadal \nd) Thiem",1,1);
class Generator
{
protected:
Task *tablica[10];
TaskCollection T1;
public:
Generator(){}
void Generuj()
{
if(T1.collection[x]->id_pyt==1)
{
tablica[i]=new Task4Answ("0",0,0);
tablica[i]->contents=T1.collection[x]->contents;
tablica[i]->id_pyt=T1.collection[x]->id_pyt;
tablica[i]->nr_pyt=T1.collection[x]->nr_pyt;
tablica[i]->help=T1.collection[x]->help; //here is the problem
}
}
}
Or maybe there is some other solution of the project im doing now.
Thanks for any help.
The problem is in this line:
tablica[i]=new Task4Answ("0",0,0);
Although you have called the Task4Answ constructor, you are also assigning the memory address returned by new to a Task pointer. Effectively, you have casted the Task4Answ pointer to a Task pointer. On the lines that follow, C++ only sees tablica[i] as a reference to a Task pointer. You need to change:
protected:
Task *tablica[10];
TaskCollection T1;
...to this:
protected:
Task4Answ *tablica[10]; // Task was changed to Task4Answ
TaskCollection T1;
That should allow C++ to see tablica as an array of Task4Answ pointers instead of Task pointers.
Edit: it looks like help is also private. You will have to change help to public or add TaskCollection::TaskCollection() as a friend. Otherwise, C++ will not let you get or set help.
Edit: the OP added that tablica[i] might contain instances of other classes that inherit from Task. In that case, you could do something like this:
void Generuj()
{
if(T1.collection[x]->id_pyt==1)
{
Task4Answ* newTask = new Task4Answ("0",0,0);
newTask->contents=T1.collection[x]->contents;
newTask->id_pyt=T1.collection[x]->id_pyt;
newTask->nr_pyt=T1.collection[x]->nr_pyt;
newTask->help=T1.collection[x]->help; // You will still have to change this from being private.
tablica[i] = newTask;
}
}
}
Later on, in order to access help, you will need to implement some sort of way of checking whether tablica[i] is a Task4Answ and not an instance of some other class that inherits from Task, perhaps by implementing a method in Task named IsTask4Answ that returns false in Task but is overridden to return True in Task4Answ. You can then cast the pointer back to Task4Answ with something like the static_cast operator. In other words:
// Add these functions to the class definitions:
virtual bool Task::IsTask4Answ() const {
return false;
}
bool Task4Answ::IsTask4Answ() const override {
return true;
}
// Later, you can do this:
if(tablica[i].IsTask4Answ()){
Task4Answ* t = static_cast<Task4Answ*>(tablica[i]);
t->help; // Again, you'll have to change this from being private.
}
Although I suggest figuring out a different data structure where you do not need to do any casting, this will allow you to access help.
Do note the virtual keyword in the first function above; it allows the function to be dynamically bound, which means that the code will check whether to call Task::IsTask4Answ() or Task4Answ::IsTask4Answ() at runtime instead of at compile time.
I have a use case that involves collections of sensor objects that return a bool (indicating the state of the sensor). In some cases the collection object is interested in the inverse of a the sensor value, but I want to use the same interface for both cases so that the collection doesn't need to track this. An example might be
Result = sensorA | not(sensorB)
where the the value of sensorA and not(sensorB) are accessed using the same interface. I've come up with a couple of solutions for this, none of which seem as simple as I originally expected the problem to be.
Firstly, I can realize the goal by creating another class that inherits from the same base interface and performs the translation. However this seems a little clunky as I have to instantiate a inverting object for each sensor:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
class ObservedSensorBase
{
public:
virtual bool getState(void) = 0;
protected:
ObservedSensorBase() { inverted = new InvertSensor(this); }
};
class ConcreteSensor : public ObservedSensorBase
{
public:
ConcreteSensor(bool state) :mState(state) {}
bool getState(void) { return mState; }
private:
bool mState;
};
class InvertSensor : public ObservedSensorBase
{
public:
InvertSensor(ObservedSensorBase *sensor) :mSensor(sensor) {}
bool getState(void) { return !mSensor->getState(); }
private:
ObservedSensorBase *mSensor;
};
int main()
{
ConcreteSensor sensorA(true);
InvertSensor notSensorA(&sensorA);
vector <class ObservedSensorBas*> sensors;
sensors.push_back(&sensorA);
sensors.push_back(¬SensorA);
for (class ObservedSensorBase* it : sensors)
{
cout << it->getState() << endl;
}
return 0;
}
Prints:
1
0
Ideally I'm looking for the original concrete sensor class to be able to return the inverted functionality. I can do this if I add a public class to each concrete sensor:
class ConcreteSensor : public ObservedSensorBase
{
public:
ConcreteSensor(bool state) :mState(state),inv(this) {}
bool getState(void) { return mState; }
class InvertSensor inv;
private:
bool mState;
};
...
sensors.push_back(&sensorA.inv);
Prints
0
but this seems a little cumbersome, as its a new variable in each concrete class. I can't add it to the base class, as InvertSensor inherits from the base, so InvertSensor isn't fully defined and can't be instantiated (at least I haven't been able to do so).
The other approach I've investigated is using an object factory:
ObservedSensorBase *invertFactory(ObservedSensorBase *sensor)
{
static map<ObservedSensorBase *, ObservedSensorBase *> m;
// Create an instance of the inverter for this object if it doesn't already exist
if (m.find(sensor) == m.end())
{
m[sensor] = new InvertSensor(sensor);
}
// Provide the inverting object for the passed sensor
return m[sensor];
}
...
sensors.push_back(invertFactory(&sensorA));
Prints
0
Is there another solution that I'm missing? Ideally something inherent in the class that each concrete instance can inherit from, but at this point it's become a bit of an intellectual challenge as well :)
--- EDIT ---
Thanks for the comments so far.
To clarify the objective better, this is for a little project for an Arduino to control signals on a model railroad. For the purposes here, assume that the signals can only show green and red. They show red when any track occupancy circuit or switch orientation that the signal is 'protecting' against indicates its unsafe for a train to proceed (and green otherwise).
Both the track detection and switch orientation objects would be concrete instances of the base sensor, but it's the switch orientation that creates this use case. If we have two signals, each of which is 'protecting' the two approaches to the two-track end of a single switch, one signal will want to use the switch orientation sensor 'as-is', and the other will want to use the inverted sensor value (to represent which way the switch is thrown).
I'm wanting to be able to invert the sensors' state representation when loading the into the signal object that holds them to avoid having to store a separate 'invert this signal' indication in the signal object, or manually instantiate a separate object that performs the inversion.
So something like
Signal1 protects SensorA (trackA) and Switch B
Signal2 protects SensorC (trackC) and not(SwitchB)
Here is an example of the signal (a container of sensors that just ORs them all together) e.g.
class Signal
{
public:
void protect(class ObservedSensorBase *sensor) { mSensors.push_back(sensor); }
void periodicLoop(void)
{
bool anyProtectedSensorActive = false;
for ( auto it = mSensors.begin();
it != mSensors.end() && !anyProtectedSensorActive;
++it)
{ anyProtectedSensorActive |= (*it)->getState(); }
if(anyProtectedSensorActive)
{ /* set Signal Red */ }
else
{ /* set signal Green */ }
}
private:
vector <class ObservedSensorBase*> mSensors; // protected sensors
};
...
Signal signal1;
Signal signal2;
signal1.protect(&sensorA);
signal1.protect(&sensorB);
signal1.protect(&sensorC);
signal1.protect(¬SensorB);
However, after playing with #Jason C's recommendation to put something in the base class (which I couldn't get working prior to asking the question, or after his suggestion) it occured to me that I could create
// Invert Sensor and ObservedSensorBase are declared as above...
class InvertedSensorBase : public ObservedSensorBase
{
public:
InvertedSensorBase() : inverted(this) {}
class InvertSensor inverted;
};
// Change the inheritance of the concrete observer
//class ConcreteSensor : public ObservedSensorBase
class ConcreteSensor : public InvertedSensorBase
And now SensorA.inverted seems to fit the bill very well.
Of course, since this is mostly a side project to return to C++ and learn C++11 after a long absence, if anyone has alternate suggestions about any point, I'd be more than happy to see them.
If you want a really no-effort solution you could store pair<ObservedSensorBase*,bool>'s in your container, where the boolean is whether you want to invert or not, and just have your logic invert the value based on that bool:
typedef pair<ObservedSensorBase *,bool> SensorWithFlag; // ...or something
vector<SensorWithFlag> sensors;
sensors.push_back(SensorWithFlag(sensor1, true)); // invert
sensors.push_back(SensorWithFlag(sensor2, false)); // don't invert
// then later when you use it, say 'n' is an index:
bool state = (sensors[n].first->getState() != sensors[n].second);
But if not, I suppose you could do the inversion in the base:
class ObservedSensorBase {
...
public:
void setInvertState (bool invertState) {
invertState_ = invertState;
}
bool getState () {
return invertState_ != getState_(); // != is xor
}
protected:
virtual bool getState_ () = 0;
private:
bool invertState_;
};
Then all subclasses implement getState_ instead of getState, and all have the ability to have their results inverted by setting setInvertState(true).
But this seems weird. Perhaps you could add some more details about how your containers are using these values. I feel like there may be a better way in general to structure your program and algorithms.
Another option is to use your "inverting filter" option but manage it in the base:
class ObservedSensorBase {
...
public:
ObservedSensorBase (...) : inv_(this) { ... }
InvertSensor * inverted () { return &inv_; }
private:
InvertSensor inv_;
};
Then you can just add mySensor->inverted() to your container when needed. This has the following caveats:
Do not call any virtual methods of ObservedSensorBase from InvertSensor's constructor.
Do not call any methods of InvertSensor that may lead to virtual base methods being called, from ObservedSensorBase's constructor.
Pointer returned by inverted() is invalidated when sensor is deleted.
The first two points are important because this won't be fully constructed yet when constructing subclasses.
This way, every sensor automatically has an inverted version of itself that comes along with it, and you don't have to manage them manually.
Yet another solution is to create wrappers around sensor objects, but keep them simple and store them directly in containers instead of storing pointers to them, to keep memory management easier. For example:
class SensorValue {
public:
SensorValue (ObservedSensorBase *s, bool invert)
: s_(s), i_(invert) { }
bool getState () { return i_ != s_->getState(); }
ObservedSensorBase * sensor () { return s_; }
private:
ObservedSensorBase *s_;
bool i_;
};
// then later, let's say you have some sensors:
ObservedSensorBase *sensor1 = ...;
ObservedSensorBase *sensor2 = ...;
// you can have containers like this:
vector<SensorValue> collection1, collection2;
// and you can use normal/inverted states as needed:
collection1.push_back(SensorValue(sensor1, false)); // normal values
collection1.push_back(SensorValue(sensor2, false));
collection2.push_back(SensorValue(sensor1, true)); // and inverted
collection2.push_back(SensorValue(sensor2, true)); // at the same time
// if you ever need the sensor object itself you can use SensorValue#sensor:
for (vector<SensorValue>::iterator i = collection1.begin();
i != collection1.end(); ++ i)
{
bool state = i->getState(); // normal or inverted, transparent to us here
ObservedSensorBase *sensor = i->sensor(); // can be used for whatever.
// note that i->getState() != i->sensor()->getState() if we're
// using an inverted SensorValue.
}
// and they aren't pointers, you can just do this with no leaks:
collection1.clear();
collection2.clear();
// although of course you still do this for sensor cleanup:
delete sensor2;
delete sensor1;
This is sort of conceptually like your inverted sensor object approach except SensorValue isn't an ObservedSensorBase, it's lightweight and cheaply copyable, and you can just store them directly in containers instead of passing around pointers.
It's very similar to storing e.g. pair<ObservedSensorBase*,bool> (where you store sensor and invert flag) in your containers instead, except unlike pair it gives you a convenient getState() member, and has some semantic meaning.
I have a class whose member itemType is only set once and never modified but it is used in many if-statements to decide which function to call.
Since itemType is only set once is there way to avoid the if statements else where in the class. This will simplify and clean the code and as a bonus will also save the overhead of if checks.
I was thinking about function a pointer taht I can initiatlize in the constructor based on the itemType value.
Is there any alternate and a better way of doing that?
Please note the original class and code base is large and I cant go around creating child classes based on itemtype.
enum ItemTypes
{
ItemTypeA,
ItemTypeB,
};
class ItemProcessing
{
public:
//This function is called hundreds of times
void ProcessOrder(Order* order)
{
//This member itemType is set only once in the constructor and never modified again
//Is there a way to not check it all the time??
if (itemtype == ItemTypes::ItemTypeA )
{
ProcessTypeA(order)
}
else if (itemtype == ItemTypes::ItemTypeB )
{
ProcessTypeB(order)
}
}
ItemProcessing(ItemTypes itype)
{
itemtype = itype; //can I do something here like setting a function pointer so I dont have to check this property in ProcessOrder() and call the relevant function directly.
}
private:
ItemTypes itemtype;
void ProcessTypeA(Order*);
void ProcessTypeB(Order*);
};
Use an array of function pointers, indexed by itemtype, like this:
typedef void(*ProcessType_func_t)(Order *);
ProcessType_func_t processType_f[] = {
ProcessTypeA,
ProcessTypeB
};
Then you can do:
void ProcessOrder(Order *order) {
ProcessType_f[itemtype](order);
}
If you have lots of different functions that need to be dispatched like this, you can use a structure.
struct {
ProcessType_func_t processType_f,
OtherType_func_t otherType_f,
...
} dispatchTable[] = {
{ ProcessTypeA, OtherTypeA, ... },
{ ProcessTypeB, OtherTypeB, ... }
};
Then you would use it as:
dispatchTable[itemtype].processType_f(order);
Finally, you could do the fully object-oriented method, by defining new classes:
class Processor { // abstract base class
public:
virtual void Process(Order *order) = 0;
};
class ProcessorA {
public:
void Process(Order *order) {
ProcessTypeA(order);
}
}
class ProcessorB {
public:
void Process(Order *order) {
ProcessTypeB(order);
}
}
Then you can have a member variable
Processor *processor;
and you initialize it when you set itemtype
ItemProcessing(ItemTypes itype)
{
itemtype = itype;
if (itemtype == ItemTypeA) {
processor = new ProcessorA;
} else {
processor = new ProcessorB;
}
}
Then you would use it as:
processor->Process(order);
This is easily expanded to support more functions that need to dispatch on itemtype -- they all become methods in the classes.
I hope I got the syntax right, I don't actually do much C++ OO programming myself.
You can consider to use either a couple of pointers to member methods or the state pattern.
The former solution has probably higher performance, while the latter is more elegant and flexible (at least from my point of view).
For further details on the state pattern, see here. This pattern fits well with your problem, even though you have to refactor a bit your classes.
I guess the first suggestion is indeed quite clear and does not require further details.
In c++ pointer to function should be mimic with virtual function and inheritance. (Polymorphism)
Define a virtual class including a pure virtual methods
processOrder ( Order* ordre);
And define subclass for each value of your enum.
You can use abstract factory pattern to creat those object or either if needed.
I can write the code if wish.
For a class, which is only defined in a header, I need a special behavior of one method for all instance of the class. It should be depending on a default value, which can be changed any time during runtime. As I do not want a factory class nor a central management class I came up with that idea:
class MyClass
{
public:
void DoAnything() // Methode which should be act depending on default set.
{
// Do some stuff
if(getDefaultBehaviour())
{
// Do it this way...
}
else
{
// Do it that way...
}
}
static bool getDefaultBehaviour(bool bSetIt=false,bool bDefaultValue=false)
{
static bool bDefault=false;
if(bSetIt)
bDefault=bDefaultValue;
return bDefault;
}
};
It works, but it looks a little awkward. I wonder if there is a better way following the same intention.
In the case where I want to use it the software already created instances of that class during startup and delivered them to different parts of the code. Eventually the program gets the information how to treat the instances (for e.g. how or where to make themselves persistent). This decision should not only affect new created instances, it should affect the instances already created.
I'd advise to use a simple method to simulate a static data member, so the usage becomes more natural:
class MyClass
{
public:
// get a reference (!) to a static variable
static bool& DefaultBehaviour()
{
static bool b = false;
return b;
}
void DoAnything() // Methode which should be act depending on default set.
{
// Do some stuff
if(DefaultBehaviour())
{
// Do it this way...
}
else
{
// Do it that way...
}
}
};
where the user can change the default at any time with
MyClass::DefaultBehaviour() = true;
My thanks to Daniel Frey with his answer which I already marked as the best. I wanted to add my final solution which is based on the answer from Frey. The class is used by some c++ beginners. As I told them to use always getter and setter methods, the way described by Frey looks very complex to beginners ("uuuh, I can give a function a value?!?!"). So I wrote the class like followed:
class MyClass
{
public:
// get a reference (!) to a static variable
static bool& getDefaultBehaviour()
{
static bool b = false;
return b;
}
static void setDefaultBehaviour(bool value)
{
getDefaultBehaviour()=value;
}
void DoAnything() // Methode which should be act depending on default set.
{
// Do some stuff
if(getDefaultBehaviour())
{
// Do it this way...
}
else
{
// Do it that way...
}
}
};
for the user, I looks now like a usual getter and setter.