【问题标题】:Best way to use a base class's private member variable in derived class在派生类中使用基类私有成员变量的最佳方法
【发布时间】:2020-05-25 01:14:29
【问题描述】:

我有下面的代码,其中基类定义了一个纯虚函数,派生类定义了这个纯虚函数,用基类的私有成员变量varvar不会被改变)执行一些计算然而)。 var 通常是一些大型结构。

从设计的角度来看,我读到通常不赞成在这种情况下将var 设为受保护成员。实现我想要的最好方法是将var作为参数传递给virtual_func()吗?

这引发了第二个问题。如果我想在virtual_func 中修改var 怎么办?这会改变你的答案吗?

class base
{
public:
  void search()
  {
    //virtual func in derived class must use var in base class, but not change var

    virtual_func();
  }

private:
  T var;
  virtual void virtual_func() = 0;
};

class derived : public base
{
  void virtual_func()
  {
    //does something with base class's var, but not alter it
  }
};

【问题讨论】:

  • 如果你想修改var 那么protected 是你的选择,我不明白你为什么不想使用它。我的意思是,您何时需要使用该关键字?因为看起来你拒绝在它设计的特定场景中使用它。

标签: c++ inheritance polymorphism virtual


【解决方案1】:

Bjarne Stroustrup,在他的书中The Design and Evolution of C++ 在第 13.9 节讨论了protected

它是为您的用例而添加的:允许派生类访问基类成员,而不会将这些成员暴露给所有人,或滥用friend 声明。五年后,提出请求的人(项目)禁止使用受保护的成员变量,因为它们成为错误和复杂维护的来源。他最后说受保护的数据不是一个好主意,但受保护的成员函数很好。

按照这些准则,您应该保留所有基类数据private,并添加protected getter 和setter 函数来访问数据。

根据您的用例以及复制数据的成本,您的 getter 可以返回数据的副本或对它的引用(或 const 引用)。返回非常量引用将允许您直接通过赋值 (getVar() = newvar;) 修改数据,或修改类的特定数据成员。返回一个 const 引用并使用一个 setter 函数,将更多地封装数据而不会过度暴露类。 setter 函数还可以让您更好地控制对 var 的更改,包括执行任何可能需要的验证。

【讨论】:

    【解决方案2】:

    如果您不想在基类中创建varprotected,可以在基类中添加publicprotected getter 函数,然后可以在派生类中调用。 类似的东西

    T getVar() const { return var; }
    

    【讨论】:

    • 啊,是的,这是另一种选择。我确实想让var 受到保护。这会让我的生活变得非常轻松,但我已经看到一些资源表明这是不好的做法。对此有何看法?
    • @Iamanon 如果您需要在派生类中读取和修改var,但又不希望继承层次结构之外的其他人访问它,那么我会说这是@ 的完美用例987654328@成员变量。
    • 在您的回答中,getVar() 正在复制var,根据 Qn,这显然是一个大型结构。通常应通过const T& 返回。
    • @iammilind 我说“有点像”。通过 (const) 引用或值返回是否有意义在这里我留给 OP。
    【解决方案3】:

    “从设计的角度来看,我读到通常不赞成在这种情况下使 var 成为受保护的成员。”

    从您阅读的任何地方来看,这似乎是一个错误的概念。如果您必须在class derived 中访问base::var,那么最佳设计决策是将var 设置为protected。其他一切都会干扰封装。除了您的问题中提到的要求之外,protected 的用例还有什么。 :-)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-11-17
      • 2012-09-16
      • 1970-01-01
      • 2017-04-14
      • 2016-05-21
      • 2015-12-11
      • 1970-01-01
      • 2017-08-07
      相关资源
      最近更新 更多