0

considere a simle class stDeriv which inherits from stBase. I'am surprised to see that we cannot access to the stDeriv class members through a stBase reference.

Below the basic example to illustrate my point :

#include <fstream>  // std::ifstream
#include <iostream> // std::cout

using namespace std;

typedef struct stBase
{
public:
  virtual ~stBase() { ; }
  stBase(int iB) { iB_ = iB; }

  // Copy operator
  stBase &operator=(const stBase &src)
  {
    iB_ = src.iB_;
    return *this;
  }

  virtual void Hello() { cout << " Hello from stBase" << endl; }

private:

  int iB_ = 0;

} stBase;

typedef struct stDeriv : public stBase
{
public:

  int iD_ = 0;

  stDeriv(int iB) : stBase(iB), iD_(0) { ; }
  virtual void Hello() { cout << " Hello from stDeriv" << endl; }

  // Copy operator
  stDeriv &operator=(const stDeriv &src)
  {
    iD_ = src.iD_;
    return *this;
  }
} stDeriv;

int main(int, char *[])
{
  int iErr = 0;
  stBase aBase(0);
  stDeriv aDeriv(1);
  stDeriv &rDeriv = aDeriv;    
  stBase &rBase = aBase;

  rBase.Hello();  // OK result : "Hello from stBase"
  rDeriv.Hello(); // OK result : "Hello from stDeriv"

  rBase = rDeriv; // KO!!! Cannot access to aDeriv.iD_ through rBase !!!
  rBase.Hello();  // KO!!!  result : "Hello from stBase" !!!

  return iErr;
}

Why do I fail to access to stDeriv::iD_ through rBase after "rBase = rDeriv;" ?

sylwa06
  • 77
  • 10
  • A Deriv is a Base, but a Base is not a Deriv. This is the reason. – Fareanor Oct 18 '21 at 11:00
  • The `typedef struct A {} A;` construct is a C-ism that, while formally valid, has no use in C++. – molbdnilo Oct 18 '21 at 11:49
  • `rBase` is a reference to `stBase`. Look at the definition of the `stBase` struct. Does it have an `iD_` member? No, it doesn't, and that's why you can't access it. – molbdnilo Oct 18 '21 at 11:52
  • 1
    `rBase = rDeriv;` does not change the reference, but the referred-to object: in your code it's equivalent to `aBase = aDeriv;`. – chi Oct 18 '21 at 12:09
  • After the line "rBase = rDeriv;", I expected to be able to visit aDeriv attributes, which is unfortunately wrong. All is clearly explained in the Pepijn Kramer' s answer below. – sylwa06 Oct 18 '21 at 14:30

1 Answers1

1

You cannot rebind references like you do. rBase already has a value and cannot be assigned to again. why doesn't C++ allow rebinding a reference?

So just make a new reference:

int main(int, char* [])
{
    int iErr = 0;
    stBase aBase(0);
    stDeriv aDeriv(1);
    stDeriv& rDeriv = aDeriv;
    stBase& rBase = aBase;

    rBase.Hello();  // OK result : "Hello from stBase"
    rDeriv.Hello(); // OK result : "Hello from stDeriv"

    // Make a new reference and all is fine
    stBase& rBase2 = rDeriv;  
    rBase2.Hello(); // OK result : "Hello from stDeriv"

    return iErr;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19