1

假设我们有两个类,Base并且Derived. 有两种方法getXsetX,它们是公共的,使用受保护的 intx与用户交互。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为私有 const int in Derived。但是,这会导致 setX 和 getX 与 Base::x 一起工作。

3) 使 Base::setX 成为虚函数,使 Derived::setX 函数什么都不做。

处理这个问题的最佳方法是什么?

4

4 回答 4

5

正如Derived公开的那样Base,您尝试做的事情没有多大意义。您应该改为使用privateorprotected继承,然后仅提供对您需要的Derived方法的访问,而不是反过来。Base

于 2013-11-06T20:54:47.307 回答
2

首先,正如 anatolyg 所观察到的,setX1) 中的遮蔽方法通过在类中使其私有Derived并不会阻止某人Base通过强制转换直接在类上调用它。

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

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

如果您只想禁止任何Derived类实例的用户调用该setX对象上的方法......但仍然在接口中拥有它,那么显然您可以按照您在 3 中提出的建议)使其成为 Base 中的虚函数并实现它中空Derived

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

如果您正在寻找的是禁止此调用的编译错误,那么您可能会重新考虑您的层次结构:

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

在这种情况下:

  • 当您real_Base的客户端代码不需要调用setX.
  • 允许Base调用时使用setX
  • 禁止Derived调用时使用。setX
于 2013-11-06T21:43:06.477 回答
1

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

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

撰写并DerivedBase它一个更好的名字:

class Composite {
private:
    Base base;
public:
    Composite() : base(3) {
    }
};
于 2013-11-06T21:13:10.100 回答
0

您不能x在 的初始化程序列表中初始化成员Derived,因为x它不是 的成员Derived。您的编译器应该发出错误。

于 2013-11-06T20:58:16.583 回答