【问题标题】:Access to derived class members through a base class reference通过基类引用访问派生类成员
【发布时间】:2021-12-05 10:20:07
【问题描述】:

考虑一个从 stBase 继承的简单类 stDeriv。 我很惊讶地发现我们无法通过 stBase 引用访问 stDeriv 类成员。

下面的基本例子来说明我的观点:

#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;
}

为什么我在“rBase = rDeriv;”之后无法通过rBase访问stDeriv::iD_ ?

【问题讨论】:

  • Deriv 是 Base,但 Base 不是 Deriv。这就是原因。
  • typedef struct A {} A; 构造是一种 C 主义,虽然形式上有效,但在 C++ 中没有用处。
  • rBase 是对stBase 的引用。查看stBase 结构的定义。它有iD_ 成员吗?不,它没有,这就是您无法访问它的原因。
  • rBase = rDeriv; 不会更改引用,而是更改引用的对象:在您的代码中,它等效于 aBase = aDeriv;
  • 在“rBase = rDeriv;”行之后,我希望能够访问aDeriv 属性,不幸的是,这是错误的。所有的一切都在下面 Pepijn Kramer 的回答中得到了清楚的解释。

标签: c++ inheritance


【解决方案1】:

您不能像以前那样重新绑定引用。 rBase 已经有一个值,不能再次分配给它。 why doesn't C++ allow rebinding a 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;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-30
    • 1970-01-01
    • 1970-01-01
    • 2013-10-08
    • 1970-01-01
    相关资源
    最近更新 更多