如何公开从基类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:
-
界面的inheritance。 当你用Java或者其他语言来实现接口作为独立实体的时候,当你公开地从C ++中的空抽象类inheritance时,也会发生这种情况。 这里你根本不关心代码,只是想告诉你的编译器和每个使用你的基类/派生类的人,这个派生类是一种特殊的基类,它具有基类的所有属性,它的行为与基类在用户看来是可见的,可以在任何algorithm中用来代替基类。
-
代码的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
公开从Base
inheritance的Base
是无论在哪里需要Base
对象, Derived
types的对象都可以。
如果您需要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; };
就我个人而言,我更喜欢模板的方式,因为它允许你从任何从Foo
inheritance的类做同样的事情。
如果你以后不需要把它作为基类,只需要基类的一些function,你可以使用组合而不是inheritance? (C#是我的第一语言,但你明白了)
class Base { public void foo(); public void bar(); }; class Derived { private Base _base; public void bar() { _base.bar(); } };