代码之家  ›  专栏  ›  技术社区  ›  Eduard Rostomyan

私人继承总是意味着“拥有”吗?

  •  12
  • Eduard Rostomyan  · 技术社区  · 6 年前

    据我最喜欢的作家说, Mr Scott Meyers , the 私有的 继承和组合意味着同样的事情aka有一个关系。因此,从组合中获得的一切(包含,当类A有类B作为其成员时)都可以通过私有继承获得,反之亦然。

    所以下面的代码应该是has-a关系,但从我的角度来看,它不是!

    class A : private boost::noncopyable {.. this is irrelevant };
    

    有人能告诉我我失踪了吗?或者如何通过组合实现这些代码?

    4 回复  |  直到 6 年前
        1
  •  15
  •   VLL Mohamed El-Nakeep    6 年前

    示例可以通过如下组合实现:

    class A {
    private:
        class B {
            B(const B&) = delete;
            B& operator=(const B&) = delete;
        } b;
    };
    

    A 是不可操作的,因为它的成员 b 是不可操作的。

        2
  •  6
  •   dbush    6 年前

    你的例子仍然是一个has-a关系。

    以下面的类为例,它大致相当于 boost:noncopyable :

    class X {
    private:
        X(const X &);
        X &operator=(const X &);
    public:
        X() {}
    };
    

    以下两个类具有相同的功能:

    class A : private X {
    public:
        int a;
        char b;
    };
    
    class B {
    public:
        int a;
        char b;
        X x;
    };
    

    在这个例子中, A 私人继承 X 虽然 B 包含的实例 X . 无法复制,因为它无法调用父级的复制构造函数,并且 无法复制,因为它无法调用其成员之一的复制构造函数。

    A a1;
    A a2(a1);   // error
    B b1;
    B b2(b1);   // error
    
        3
  •  4
  •   YSC    6 年前

    boost::noncopyable 没有真正的语义意义,这只是一个实现细节,不允许孙子。

    class A : private boost::noncopyable {};
    

    A 有一个 boost::不可操作 ,因为 boost::不可操作 无论是字面上还是意义上都是空的。在这里,你会说“ 是不可操作的”,但我一般同意迈耶斯在一般情况下的观点。

        4
  •  1
  •   sdenham    6 年前

    这个问题可以用一种避免讨论某个具体例子的方式来回答。一个公开继承的类从定义其父类语义的所有内容开始——它的公共函数,以及它的公共状态变量(如果有的话)。如果这些都没有被重写,则它符合 Liskov substitution principle 这是一个被广泛接受的设计原则,即重写这些属性时应保持可替换性。

    对于私有继承,除非程序员选择在派生类中以保留可替换性的方式实现(或重新实现)父类的所有公共属性,否则这些都不适用。由于C++不需要一个私有派生类来实现其父的公共方法和变量的版本,因此,如果派生类取代了父类作为私有成员的实例,那么这与代码中的小的和公式化的更改无关。特别是,对于私有继承,派生类在任何功能或操作上都不是父类类型的子类型,如果您的语言将派生类视为子类型,则会造成误解和混淆(尽管应该注意D,除非你的语言有一种方法来执行子类型(C++没有)的语义有效性,那么这实际上是一个风格问题。