-1

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?

  • 1
    which book are you learning this from?? – Nim Jun 08 '16 at 21:17
  • Also, why do you want to pass "Disturb" as a pointer? The problem is a lot simpler if you just need `City::City(bool Disturb)`. – kfsone Jun 08 '16 at 21:18
  • The person and animal objects are in their respective Person and Animal classes with their own different attributes. kfsone, can i do _person.IsDead and save it to a member in my miami object? – LilProgramma Jun 08 '16 at 21:20
  • And if using a pointer, you need to dereference it: if(*Disturb == true). Do not compare against true or false, simply do if(someBool) or, if you wanted to check the opposite, if(!someBool) – Aconcagua Jun 08 '16 at 21:20
  • I also want to later be able to do miami.Disturbance == true, and it'd check the _person.IsDead's current value. – LilProgramma Jun 08 '16 at 21:23
  • 1
    @kfsone `->` (member access) precedes `&` (address of). So _person and _animal are already pointers, and the result of &name->IsWhatever is a pointer of type bool* to name->IsWhatever. – Aconcagua Jun 08 '16 at 21:26
  • @LilProgramma Why all these pointers and address-of operations? You don't need to do that. – πάντα ῥεῖ Jun 08 '16 at 21:43
  • 1
    Why would members of the classes be passed as parameter to a `City` constructor? There is zero relationship there; that is very bad Object Oriented Design. – NonCreature0714 Jun 08 '16 at 21:43
  • @NonCreature0714 this is an analogy, it is simplified to help with alternatives for my embedded design requiring each object to obtain the locations of the states of different sensors. – LilProgramma Jun 08 '16 at 21:51
  • @LilProgramma You probably simplified your example too much to give you a concise answer. – πάντα ῥεῖ Jun 08 '16 at 21:53
  • @LilProgramma ah, okay, forgive me for being too literal. That information may actually be useful amplifying information in your question btw, it really paints of a picture of what you're trying to accomplish. – NonCreature0714 Jun 08 '16 at 21:54
  • @LilProgramma by "locations of the states of different sensors," do you mean the location of a sensor in a certain state? – NonCreature0714 Jun 08 '16 at 21:58
  • @LilProgramma Why are you using such weird semantical analogies if we're talking about a sensor driven system actually? – πάντα ῥεῖ Jun 08 '16 at 22:01
  • 1
    @LilProgramma if you rewrite your question and clarify you are writing code for remote sensors, and change `City` to `Sensor`, and `Person` to `RemoteSensorA` (or something like that), and `animal` to `RemoteSensorB`, you probably get a much better, helpful and accurate answer. *Especially* because it looks you are actually trying to keep a group of instances of actively "disturbed" sensors by creating new instances when sensors detect disturbance. – NonCreature0714 Jun 08 '16 at 22:03
  • @NonCreature0714 so pretty much just trying to simplify &_person->IsDead into one "thing" and save it to a member so that i can just reuse it in more complex statements requiring an address. Something like QT's connect() which requires the member itself. – LilProgramma Jun 08 '16 at 22:03
  • @LilProgramma I edited my comment above, I think I clarifies a little better what will help you find a solution. – NonCreature0714 Jun 08 '16 at 22:07

3 Answers3

2

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.

Community
  • 1
  • 1
Aconcagua
  • 24,880
  • 4
  • 34
  • 59
  • 1
    `City miami = new ....` Sure? This isn't java. – πάντα ῥεῖ Jun 08 '16 at 21:48
  • Its for an embedded system requiring to know the states of multiple sensors each with their own classes, its just simplified with different names so its easier to read. – LilProgramma Jun 08 '16 at 21:53
  • 1
    That does explain the likely intent of the question which seemed an odd mixture of unrelated classes at first sight. +1 for suggesting the cause of the disturbance notify the City object (and for working out what the question was about). @LilProgramma better to use real names like Sensor, Controller or whatever so people understand what you need. – John D Jun 08 '16 at 21:58
  • @πάνταῥεῖ Was editing already. Suppose I should get used to write the code in an IDE instead of directly here... – Aconcagua Jun 08 '16 at 21:58
  • @LilProgramma That's an important hint. You should include this in your question next time, most of us are quite aware that things work differently in embedded environments. And I join John D, leave the real names. Your naming drove me into an entirely different direction... – Aconcagua Jun 08 '16 at 22:07
  • @Remy Lebeau Awesome, thanks for the detail! I changed the type from Boolean to a custom "BoolPlus" type which contains a bool, but also emits a signal(HasChanged()) whenever it is changed. would I be able to use the connect statement: Connect(sensorAddress, HasChanged(), this, NotOverLimit()) to connect it to a function in the Sensor classes? – LilProgramma Jun 08 '16 at 23:47
  • @LilProgramma: I'm not familiar with Qt or its signal/slot mechanism, but after a cursory glance through its [documentation](http://doc.qt.io/qt-4.8/signalsandslots.html), I'm sure you can do something similar to what you are thinking. – Remy Lebeau Jun 09 '16 at 00:48
  • @LilProgramma May I assume the following: Your bool variables represent flags that are set or unset from within an *interrupt* (!). This is then the reason why you can't or don't want to call `someFunction` directly from where the flags are set (that would be the most simple...). Then in your main loop, you check these flags periodically to react appropriately. Is this correct so far? – Aconcagua Jun 09 '16 at 04:38
  • @LilProgramma Added a polymorphic approach. Maybe this is interesting for you? – Aconcagua Jun 09 '16 at 05:17
1

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();
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • As I discovered, he's using `&_name->` because `name` is a pointer and he's dereferencing it to reach it's `IsDead` member and then taking the address of that. – kfsone Jun 08 '16 at 21:45
  • Should have thought myself of references... +1. – Aconcagua Jun 08 '16 at 22:15
0

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!

Community
  • 1
  • 1
tatertot
  • 123
  • 2
  • 11
  • I was just wondering if there was an easy reusable way to access different member locations. My more complex problem is to turn that Bool into a custom data type which also contains a function that whenever the Bool changes, it will send a QT signal to tell the City object that it has changed states. Thus, I would need to reference IsDead for the connect() statement. – LilProgramma Jun 08 '16 at 21:48
  • @LilProgramma: you are going down a bad rabbit hole with this awful code design. I would have each Person or Animal contain a pointer to a City they belong to, and if the Person/Animal dies then it can notify the City directly. – Remy Lebeau Jun 08 '16 at 21:54
  • @LilProgramma Just as clarification, does your City object contain all of your person and animal objects? Right now it seems that based on what you're trying to do, you need a little work on your object design. If your Person and Animal objects are contained in the city, then it will be much easier to do what you're trying to do. Also, Remy's comment is another (possibly better) design, depending on how connected you want your objects to be. – tatertot Jun 08 '16 at 21:54
  • @tatertot the person and animal objects are contained respectively in seperate Person and Animal Classes with their own seperate attributes and methods. While the City class contains the cities: miami, detroit... – LilProgramma Jun 08 '16 at 21:57
  • @LilProgramma I think that design is your problem. Your City class is just a list of the city names? How about you make your City class much more useful by having each city have a name, city attributes, and then create an enclosing class for cities (State, Country, County, CityList, etc.) – tatertot Jun 08 '16 at 22:00