0

I have two classes where the first one is instantiated in an object wich is used inside another object of class 'two'. The problem I have is when trying to access the members of the object of first class through the object of second class.

I'm using this approach on arduino to instantiate an object wich controls a LCD with LiquidCrystal_I2C class wich needs parameters as soon is instantiated.

Example code:

    #include <iostream>

    using namespace std;

    class A
    {
    public:
      int data;
      int state;
        A (int); // Constructor needs parameter
      void setState (int);
      int getState ();
    };

    A::A (int newdata)
    {
      data = newdata;
    }

    void A::setState (int newstate)
    {
      state = newstate;
    }

    int A::getState ()
    {
      return state;
    }

    class B
    {
    public:
      A * a;
      int aState;
        B ();
      void attachA (int);
      void printall ();
    };

    B::B ()
    {
    }

    void B::attachA (int data)
    {
      A newobj (data);
      a = &newobj;
      a->setState (data + 1);
      aState = a->getState ();
      cout << "B obj. address?: " << this <<
        ", 'A' class obj. creation with data: " << data << " B.a->getState(): " <<
        a->getState () << ", B.a->data: " << a->data << "\n";
    }

    void B::printall ()
    {
      cout << "B obj. address?: " << this << ", 'A' member class address?: " << a
        << ", B.aState: " << aState << ", B.a->getState(): " << a->
        getState () << ", B.a->data: " << a->data << "\n";
    }

    int main ()
    {
      B temp_one;
      temp_one.attachA (123);

      B temp_two;
      temp_two.attachA (345);

      temp_one.printall ();
      temp_two.printall ();

      temp_one.printall ();

      temp_one.a->setState (42);
      temp_one.printall ();

      return 0;
    }

This prints:

B obj. address?: 0x7ffe088aa130, 'A' class obj. creation with data: 123 B.a->getState(): 124, B.a->data: 123                                                                       
B obj. address?: 0x7ffe088aa140, 'A' class obj. creation with data: 345 B.a->getState(): 346, B.a->data: 345                                                                       
B obj. address?: 0x7ffe088aa130, 'A' member class address?: 0x7ffe088aa108, B.aState: 124, B.a->getState(): 0, B.a->data: 4196144                                                  
B obj. address?: 0x7ffe088aa140, 'A' member class address?: 0x7ffe088aa108, B.aState: 346, B.a->getState(): 0, B.a->data: 4196144                                                  
B obj. address?: 0x7ffe088aa130, 'A' member class address?: 0x7ffe088aa108, B.aState: 124, B.a->getState(): 0, B.a->data: 4196144                                                  
B obj. address?: 0x7ffe088aa130, 'A' member class address?: 0x7ffe088aa108, B.aState: 124, B.a->getState(): 0, B.a->data: 4196144          
Hans
  • 39
  • 4
  • 1
    Does this answer your question? [Can a local variable's memory be accessed outside its scope?](https://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope) – Algirdas Preidžius Mar 20 '20 at 15:19
  • When you create `newobj` in `attachA` it has local duration. The object is destroyed at the end of its scope (at the exit of `attachA`) and any dereference of that address is undefined behavior. Your options are to make `A a` a member variable of `B` (instead of `A* a`, or to dynamically allocate `newobj` in `attachA`. I like the former, especially if it makes sense in your program design for each `B` to own its own `A`. – JohnFilleau Mar 20 '20 at 15:19
  • Can you please clarify what output you expect? – Werner Henze Mar 20 '20 at 15:25
  • @WernerHenze Delegate the creation of the object of class A to the object of class B and owns it (like John said). Concretely [this](https://stackoverflow.com/questions/30412572/call-function-on-lcd-object-in-class), but creating the 'A class' object inside 'B class' (or LiquidCrystal_I2C and Display class on post). – Hans Mar 20 '20 at 15:52
  • @John Got it, thank you very much!. Found [another question](https://stackoverflow.com/questions/30412572/call-function-on-lcd-object-in-class) where the OP takes another approach to achieve a similar result. – Hans Mar 20 '20 at 15:59
  • What pattern are you following? Other comments & replies have already clarified the details of flaws in your code snippet. But I want to delve deeper into your mindset. On embedded platforms, memory management is a major concern and heap is normally disliked. You gotta carefully choose your design pattern first. – Red.Wave Mar 20 '20 at 16:11
  • @Red.Wave Hi, I'm currently refactoring an arduino program to OOP. I'm not using a specific design pattern (neither being excel at knowing them), just want to abstract by the creation of another class, the logic behind the use of print and setCursor methods of a LiquidCrystal_I2C class object, and delegate the creation of an object of this class. In this way I expect to get a more declarative code at main loop. – Hans Mar 21 '20 at 18:06
  • As I wrote earlier, memory mgmt is a major concern on embedded platforms. But in case you really prefere PIPML idiom, `std::unique_ptr` may be a good starting point. Compile errors might bite you, but once finished, there are at least some minimum guarantees against runtime errors. – Red.Wave Mar 23 '20 at 14:44

1 Answers1

0

I didn't inspect is all to well, but I encountered this error before.

In attachA you create a temp object and save its address. This should not be done as the object gets destructed at the end of the method.

So you have an address to somewhere on the stack (because stack-local variable). On the invocation of the method on the other object, the stack frame is the same by (more or less) chance and the object resides in the same location.

So both addresses end up the same (and incidentally invalid).

Martin B.
  • 1,567
  • 14
  • 26
  • Also [don't be afraid of returning by value](https://blog.knatten.org/2011/08/26/dont-be-afraid-of-returning-by-value-know-the-return-value-optimization/) – Martin B. Mar 26 '20 at 11:39