0

For certain reasons, I want to have multiple instances of class A all have access to a single instance of class B. B has public member functions that allow objects of A to get data from B, but not to change it. I'm trying to do this by declaring an object of B in my main function, then passing it to the constructor when I declare objects of type A.

void main () {
  B obj_b;
  A A1(obj_b);
  A A2(obj_b);
  A A3(obj_b);  

  cout << A1.getfoo() << endl;
  cout << A2.getfoo() << endl;
  count << A3.getfoo() << endl;
}

class B{
  private:
    int foo = 9;
  public:
    int getfoo(){return foo;}
};

class A {
  private:
    B *bptr;

  public:
    A(B b){ this->bptr = &b; }
    int getfoo(){ return bptr->getfoo(); }
};

This compiles and runs, but I get very weird results. The return values from getfoo are sometimes correct sometimes incorrect. Am I handling the pointers incorrectly? Is there a better way to do this?

Robert M.
  • 575
  • 5
  • 17
  • Sidenote, [`void main()` is prohibited by the C++ standard and should not be used](https://stackoverflow.com/a/204483/12861639). `main` should return `int` instead. – Ranoiaetep Jan 19 '23 at 07:29
  • 1
    Roger that. I'm actually working in the Arduino environment where the "main" function is void loop(){} instead. – Robert M. Jan 19 '23 at 16:58

1 Answers1

3

In the A constructor, the argument b is a local variable, its life-time ends when the constructor function ends. You can't save a pointer to it, that pointer will become invalid immediately.

Either use smart pointers, or use a reference and constructor initializer lists:

class A
{
public:
    // Pass by reference
    A(B& b)
        : b{ b }  // Initialize the member variable b with the argument b
    {
        // Empty body
    }

private:
    B& b;  // Reference to a B object
};
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • I see. Does that mean that when obj_b is passed to the constructor for A, a *copy* of obj_b is created and passed? – Robert M. Jan 19 '23 at 16:57
  • 1
    @RobertM. With your *current* (as shown in the question) then yes. – Some programmer dude Jan 19 '23 at 17:04
  • That worked! Thank you so much. I wasn't aware of either references or constructor initializer lists. I will research those as well as smart pointers. Is the initializer list necessary with a reference? Will a copy initialization produce ill effects? – Robert M. Jan 19 '23 at 21:47
  • @RobertM. It's not possible to assign to a reference, only initialize it. Assignment to a reference is really assignment to the variable it references. – Some programmer dude Jan 20 '23 at 05:14
  • That's why a copy initialization wouldn't work? i.e. – Robert M. Jan 20 '23 at 18:08
  • @RobertM. Copy-initialization of a reference will work, for example `int a = 5; int& ref1 = a; int& ref2 = ref1;` The initialization of `ref2` will create a copy of `ref1`, both references will reference the same variable `a`. Copy-assignment will not work, for example `int a = 0, b = 1; int& refa = a; int& refb = b; refa = refb;` The assignment `refa = refb` will be equivalent to `a = b`, and it won't copy the actual reference itself. – Some programmer dude Jan 20 '23 at 18:45