【问题标题】:Derived class variable scope c++派生类变量范围c ++
【发布时间】:2013-11-18 07:22:27
【问题描述】:

假设我们有两个类,BaseDerived。有两种方法,getXsetX,它们是公共的,并使用受保护的 int x 与用户交互。 Base 构造集 x 为 1,Derived 构造集 x 为 3。

class Base {
public:
    Base();
    int getX();
    void setX(int n);
protected:
    int x;
}

int Base::getX() {
    return x;
}

void Base::setX(int n) {
    x = n;
}

Base::Base() : x(1) {
}

class Derived : public Base {
public:
    Derived();
}

Derived::Derived() : x(3) {
}

Derived 类可以完全访问 Base 中的方法。太好了。

假设出于某种原因,我不希望 setXDerived 类的用户可用。我想到了几种方法。

1) 将 setX 重新声明为 Derived 中的私有,因此阴影会阻止用户完全访问该方法。

2) 将 x 重新声明为 Derived 中的私有 const int。但是,这会导致 setX 和 getX 与 Base::x 一起工作。

3) 将 Base::setX 设为虚函数,将 Derived::setX 设为不做任何事情的函数。

最好的处理方法是什么?

【问题讨论】:

  • 您应该创建一个Base(int n) 构造函数,然后您可以执行Derived::Derived() : Base(3) {},因为现在您的代码无法编译。
  • 如果您使用方法 1,可能会以冗长的方式访问隐藏函数:Derived d; d.Base::SetX(9); - 这种可能性是否适合您的设计,或者您是否也想阻止它?

标签: c++ inheritance


【解决方案1】:

首先,正如 anatolyg 所观察到的,通过在 Derived 类中将其设为私有来隐藏 1) 中的 setX 方法不会阻止有人通过强制转换直接在 Base 类上调用它。

所以 1) 只有在您接受这一点时才可以。

否则,如果您只想在Base 类中向许多派生类提供setX 的实现,但不向Base 或派生类用户公开。只需在 Base 类中保护 setX 方法即可。在这种情况下,您也可以将 x 设为私有,并从 Derived 构造函数调用 setX 方法。

如果您只想禁止Derived 类的任何实例的用户调用该对象上的setX 方法...但仍然在界面中保留它,那么显然您可以按照您在 3) 中提出的建议它是 Base 中的一个虚函数,并在 Derived 中实现它为空。

但在这种情况下,您违背了“is a”的继承座右铭(显然您的派生类的行为不像 Base 类)。

如果您正在查看的是禁止此调用的编译错误, 也许你可以重新考虑你的层次结构:

  • class real_Base; 没有实现 setX 方法
  • class Base : public real_Base; 实现了setX 方法
  • class Derived : public real_Base; 没有实现 setX 方法

在这种情况下:

  • 当您的客户端代码不需要调用setX 时,您可以使用real_Base 作为接口。
  • 当允许调用setX 时使用Base
  • 在禁止调用setX 时使用Derived

【讨论】:

    【解决方案2】:

    您没有覆盖任何虚函数,因此继承是可疑的。

    您希望用户使用Base 接口还是Derived 接口?如果你说Derived,那又是可疑的。

    Base 编写Derived 并给它起一个更好的名字:

    class Composite {
    private:
        Base base;
    public:
        Composite() : base(3) {
        }
    };
    

    【讨论】:

      【解决方案3】:

      您不能在Derived 的初始化列表中初始化成员x,因为x 不是Derived 的成员。你的编译器应该会报错。

      【讨论】:

        【解决方案4】:

        作为Derived 公开派生自Base,您尝试做的事情没有多大意义。您应该改为使用privateprotected 继承,然后在Derived 中仅提供对Base 中您需要的方法的访问,而不是其他方式。

        【讨论】:

        • 只有在某些虚函数需要重写时,我才会私下派生。否则我会作曲。
        猜你喜欢
        • 1970-01-01
        • 2017-10-30
        • 2012-02-24
        • 1970-01-01
        • 1970-01-01
        • 2018-05-19
        • 2014-02-13
        • 1970-01-01
        • 2017-04-12
        相关资源
        最近更新 更多