【问题标题】:Inheritance and hiding parent's attributes继承和隐藏父属性
【发布时间】:2012-11-22 16:30:40
【问题描述】:

这样做合理吗?

注意:这是一个最小的工作示例

class A {
    public:
        int getX() { return x; }
    protected:
        int x;
        virtual void setX(int newX) = 0;
};

// Children can modify X
class Can_Modify_X : public A {
     protected:
         void setX(int newX) { x = newX; }
     private:
         using A::x;
};

// Children can't modify X
class Can_Not_Modify_X : public A {
     private:
         void setX(int newX) { }
         using A::x;
};

我知道我 can't simply hide 一个函数,因为这会违反 Liskov 原则,但是执行 private 继承并再次指定所有公共方法似乎真的是多余的。

这两个类必须有一个共同的父类(即使它直接是其中之一),并且不能直接修改x

BONUS:有人可以指出我在这种情况下定义using 的确切行为的地方吗?我尝试用谷歌搜索它,但收效甚微。

【问题讨论】:

  • 但这是一个纯粹的虚拟,它的可见性甚至无关紧要,因为它的孩子可以在实现它时改变它。在这里只重要的是其他实体不能创建 A* 并从那里调用虚函数。还是不行?
  • “你不能”是什么意思?它确实编译了,我在这里打破了什么?

标签: c++ inheritance attributes virtual using-declaration


【解决方案1】:

我知道我不能简单地隐藏一个函数,因为那会违反 Liskov 原则。

完全相同的概念也适用于数据成员。

假设您有一个指向Can_Modify_XCan_Not_Modify_X 实例的指针(或引用)。您不能通过此引用访问或修改数据成员x。如果你将这个派生类指针向上转换为指向类A 的指针,你突然可以修改数据成员x。通过将 x 设为私有,您违反了 Liskov 替换原则。 x 是数据成员、成员函数还是类型定义都没有关系。你违反了 Liskov 替换,纯粹而简单。

派生类不应隐藏父类提供的功能。

【讨论】:

  • 但是由于x 在我的基类中受到保护,实际上没有人会知道,不是吗?类本身是不可实例化的,所以那里没有问题。指向类A 的指针无法访问x,因为它受到保护。任何从A 派生的成瘾类都可以根据需要访问x,因为它受到保护,所以没关系。唯一的区别是Can_Modify_XCan_Not_Modify_X 的孩子,但这无关紧要,因为这是课程的重点。我看不出有什么特殊情况会破坏这个东西。有没有?
  • 我什至尝试扩展 Can_Not_Modify_X 并创建一个函数将孩子本身转换为 A 并尝试像这样访问 x,但编译器拒绝接受它。
【解决方案2】:

你希望下面的代码做什么?

A * a = new Can_Not_Modify_X();
a->setX(10);

【讨论】:

  • 这不是真正的答案。
  • @Pete 现在我意识到我本可以在这方面表现得更外交一点,但我相信这是一个答案,因为它解释了为什么如果没有母乳喂养答案就不是一个好主意。 "Why can't [insert language] do that?" 的 90%(编造统计数据)问题很容易回答,只需问自己您希望它准确做什么并意识到它没有任何意义或过于复杂以至于它成为实现的噩梦。跨度>
  • 我明白了,但无论如何您的示例总是会失败,因为 setX 是私有的或受保护的。它永远不会公开是一个类,但这与原始问题无关。
【解决方案3】:

这是一个主观问题,所以我的回答也相应地主观。

我要说不,这不合理。 protected 属性使子类很容易意外地改变状态并违反不变量,所以我建议完全避免它们。然后你的父类将通过其公共或受保护的接口维护x(希望通过一组有意义的方法,而不仅仅是修改器)。

那么您不需要更改子项的可访问性,因为您的界面已经适当地控制了访问。

不仅如此,更改成员或方法的可访问性违反了最小意外原则,并且很可能会给您未来的维护者带来问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 2017-09-21
    • 1970-01-01
    • 2012-12-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多