C++ 如何从基类公开继承,但在派生类中使基类中的某些公共方法私有?
例如,类C++ 如何从基类公开继承,但在派生类中使基类中的某些公共方法私有?,c++,C++,例如,类Base有两个公共方法:foo()和bar()。类派生的继承自类基。在类Derived中,我想将foo()设置为公共,但将bar()设置为私有。下面的代码是正确和自然的方法吗 class Base { public: void foo(); void bar(); }; class Derived : public Base { private: void bar(); }; 实际上没有办法做你想做的事情,因为如果你从Base公开派生,该类的
Base
有两个公共方法:foo()
和bar()
。类派生的
继承自类基
。在类Derived
中,我想将foo()
设置为公共,但将bar()
设置为私有。下面的代码是正确和自然的方法吗
class Base {
public:
void foo();
void bar();
};
class Derived : public Base {
private:
void bar();
};
实际上没有办法做你想做的事情,因为如果你从
Base
公开派生,该类的用户将始终能够:
Derived d;
Base& b = d;
b.bar();
在从基类公开派生的类中不可访问公共基类函数是不“正确或自然的”;相反,基类接口应该被重构,使得这些函数不是公共的或被拆分成单独的类。 < P> C++ 03标准的第11.3节描述了这种能力: 11.3访问声明
访问 基类的成员可以更改 在派生类中,通过提及 派生类中的限定id 宣言。这样的提及被称为 访问声明。影响 访问声明限定id;是 定义为等同于 使用限定id的声明 因此,有两种方法可以做到这一点 注意:如ISO C++ + 11所示,在注释中禁止访问声明(<代码> BAS::Bar;< /Cord>)。应该使用using声明(
使用Base::bar;
)
1) 您可以使用公共继承,然后将bar设置为私有:
class Base {
public:
void foo(){}
void bar(){}
};
class Derived : public Base {
private:
using Base::bar;
};
2) 您可以使用私有继承,然后将foo公开:
class Base {
public:
void foo(){}
void bar(){}
};
class Derived : private Base {
public:
using Base::foo;
};
注意:如果您有一个Base类型的指针或引用,其中包含一个派生类型的对象,那么用户仍然可以调用该成员 假设您有:
class Foo{
public:
void method1();
void method2();
void notGonnaSeeIt();
private:
//stuff
};
为了有效地包装它,您可以执行私有继承并将您想要的方法传递给公共声明,如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;
};
模板
分类栏{
公众:
条(T*_输入):m_输入(_输入){}
void methodA(){m_Input->method1();}
void methodB(){m_Input->method2();}
//你还需要/想要什么
私人:
T*m_输入;
};
就个人而言,我更喜欢模板方式,因为它允许您对从
Foo
继承的任何类执行相同的操作。如果您以后不需要将其视为基类,并且只需要基类的一些函数,您可以使用组合而不是继承?(C#是我的第一语言,但你明白了)
首先,您必须从OOP的角度理解您想要做什么。有两种完全不同的继承类型:
C++中的公共继承是两种类型的混合,您得到接口继承,也获得代码继承。私有继承是另一种类型的野兽,你只能得到代码继承,派生类的用户不能用它来代替基类,从用户的角度来看,基类和派生类没有任何关系
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.
由于您想要更改接口,不应该使用公共继承,通过更改接口,您可以有效地表示这两个类具有不同的行为,不能互换使用。因此,您真正想要的是私下继承,然后将所有您想要的方法公开,而不是反过来根据,公共继承应该是“is-a”模型。您所说的派生的公开继承自Base
是,无论哪里需要Base
对象,类型为派生的
的对象就可以了
如果您要求Derived
隐藏一些可用于Base
的操作,那么您建模的不是“is-a”,公共继承不是正确的工具
正如其他答案所详述的,您想要的是私有继承或组合class Base {
public:
void foo();
void bar();
};
class Derived : public Base {
private:
using Base::bar;
};
这确保了不能从派生类外部访问Base::bar()。当然,它仍然可以从基类之外访问。-1因为你认为它不能做是错误的,但是+1因为你认为它可能不应该做是正确的。那么通过私有访问进行反向派生,然后将所需函数公开呢?@jamesMcNellis抱歉,我不明白你在说什么,表示Brian R.Bondy给出的答案是错误的?请你给我解释一下。我是C++
+1的学生和新手:这是可以做到的,但它是用来授予访问权限的,而不是限制访问权限的。我只是从语言功能方面选择了这个答案作为公认的答案,不是从ODE最佳实践方面。- 1使用弃用<代码> BAS::FoO < /C> >代替<代码>使用Base::Foo< /Co> > <代码> Base:Foo< /Case>在C++ 03中被弃用了吗?如果它被禁止在C++ 11上,我不理解-- 1,因为答案是
class Base {
public:
void foo();
void bar();
};
class Derived : public Base {
private:
using Base::bar;
};