如何公开从基类inheritance,但在派生类中从基类私有的一些公共方法?

例如, Base类有两个公共方法: foo()bar()Derived类从Base类inheritance。 在类Derived ,我想使foo()公开,但bar()私有。 下面的代码是正确和自然的方式来做到这一点?

 class Base { public: void foo(); void bar(); }; class Derived : public Base { private: void bar(); }; 

C ++ '03标准的第11.3节描述了这种能力:

11.3访问声明
通过在派生类声明中提及它的限定标识,可以在派生类中更改基类成员的访问权限。 这样的提到被称为访问声明。 访问声明合格ID的效果; 被定义为等同于使用qualified-id的声明

所以有两种方法可以做到这一点。

注:从ISO C ++ '11开始,禁止访问声明( Base::bar; ),如注释中所述。 应该使用using声明( using Base::bar; )。

1)你可以使用公有inheritance,然后使酒吧私人:

 class Base { public: void foo(){} void bar(){} }; class Derived : public Base { private: using Base::bar; }; 

2)你可以使用私有inheritance,然后公布foo:

 class Base { public: void foo(){} void bar(){} }; class Derived : private Base { public: using Base::foo; }; 

注意:如果你有一个包含Derivedtypes的对象的Basetypes的指针或引用,那么用户仍然可以调用成员。

没有办法做你想做的事情,因为如果你从Base公开派生出来,这个类的用户总是能够:

 Derived d; Base& b = d; b.bar(); 

在基类派生的类中,使公共基类的function不可行是不正确的或自然的; 相反,基类接口应该被重构,使得这些函数不是公有的,或者被分成一个单独的类。

首先,你必须从OOP的angular度来理解你想要做什么。 有两种完全不同的inheritancetypes:

  1. 界面的inheritance。 当你用Java或者其他语言来实现接口作为独立实体的时候,当你公开地从C ++中的空抽象类inheritance时,也会发生这种情况。 这里你根本不关心代码,只是想告诉你的编译器和每个使用你的基类/派生类的人,这个派生类是一种特殊的基类,它具有基类的所有属性,它的行为与基类在用户看来是可见的,可以在任何algorithm中用来代替基类。

  2. 代码的inheritance。 在基类中有一段代码要在派生类中重用。 基类和派生类不必以任何方式相关,你只是想重用代码,就是这样。

C ++中的公共inheritance是两种types的混合,你得到了接口inheritance,并且你也获得了代码inheritance。 私有inheritance是一种不同的野兽, 只有代码inheritance,派生类的用户不能使用它而不是基类,从用户的angular度来看,基类和派生类没有任何关系。

 struct Base {}; struct PublicDerived : public Base {}; struct PrivateDerived: private Base {}; Base * base; PublicDerived * public_derived; PrivateDerived * private_derived; base = public_derived; //good base = private_derived; //compilation error. 

既然你想改变接口,你不应该去公开inheritance,通过改变接口你有效地说这两个类有不同的行为,不能交替使用。 所以你真正想要的是私下inheritance,然后把你想要的所有方法公诸于世,而不是相反

根据Liskov替代原则 ,公共inheritance应该模拟“是-a ”。 Derived公开从Baseinheritance的Base是无论在哪里需要Base对象, Derivedtypes的对象都可以。

如果您需要Derived隐藏一些可用于Base ,那么您正在build模的内容是“is-a”以外的内容,公共inheritance不是正确的工具。

你想要的是私人inheritance或组合,因为其他答案已经详细。

假设你有这个:

 class Foo{ public: void method1(); void method2(); void notGonnaSeeIt(); private: //stuff }; 

为了有效地包装它,你可以做一个私有inheritance,并将你想要的方法传给像Brian这样的公共声明:

 class Bar : private Foo{ void methodA(){ method1(); } void methodB(){ method2(); } //more stuff }; 

或者你可以用装饰器包装它

 template<class T> class Bar{ public: Bar(T *_input) : m_Input(_input){} void methodA() { m_Input->method1(); } void methodB() { m_Input->method2(); } //whatever else you need/want private: T* m_Input; }; 

就我个人而言,我更喜欢模板的方式,因为它允许你从任何从Fooinheritance的类做同样的事情。

如果你以后不需要把它作为基类,只需要基类的一些function,你可以使用组合而不是inheritance? (C#是我的第一语言,但你明白了)

 class Base { public void foo(); public void bar(); }; class Derived { private Base _base; public void bar() { _base.bar(); } };