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

pow*_*boy 57 c++

例如,class Base有两个公共方法:foo()bar().类Derived继承自类Base.在课堂上Derived,我想foo()公开但bar()私下.以下代码是正确和自然的方式吗?

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

class Derived : public Base {
   private:
     void bar();
};
Run Code Online (Sandbox Code Playgroud)

Bri*_*ndy 91

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

11.3访问声明
通过在派生类声明中提及其qualified-id,可以在派生类中更改基类成员的访问权限.这种提及称为访问声明.访问声明qual-id的效果; 被定义为等同于使用qualified-id的声明

所以有两种方法可以做到.

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

1)您可以使用公共继承,然后使栏私有:

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

class Derived : public Base {
private:
    using Base::bar;
};
Run Code Online (Sandbox Code Playgroud)

2)你可以使用私有继承,然后使foo公开:

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

class Derived : private Base {
public:
    using Base::foo;
};
Run Code Online (Sandbox Code Playgroud)

注意:如果你有一个Base类型的指针或引用,它包含Derived类型的对象,那么用户仍然可以调用该成员.

  • +1:可以这样做,但它用于授予访问权限,而不是限制它. (5认同)
  • 在C++ 03中是否弃用了"Base :: foo"?如果它在C++ 11上被弃用,我不理解-1,因为答案在这一刻是正确的. (5认同)
  • -1使用弃用的`Base :: foo`而不是`using Base :: foo` (2认同)
  • 访问声明是否会阻止我们将指向派生类的实例的指针/引用转换为基类的实例,然后访问“隐藏”的成员?我对此功能本应涵盖的用例表示怀疑,但我仍然很好奇。 (2认同)

Jam*_*lis 13

实际上没有办法做你想做的事情,因为如果你公开派生Base,那么班级的用户将始终能够:

Derived d;
Base& b = d;
b.bar();
Run Code Online (Sandbox Code Playgroud)

在基类的类派生publicy中使公共基类函数不可访问是"正确或自然的"; 相反,应该重构基类接口,使这些函数不公开或分成单独的类.

  • -1 因为你断言它不能做是错误的,但 +1 因为你断言它可能不应该做是正确的 (2认同)

vav*_*ava 8

首先,您必须从OOP角度了解您想要做什么.有两种完全不同的继承类型:

  1. 接口的继承.当您implement使用Java或其他语言将接口作为独立实体时,当您从C++中公开继承空抽象类时,也会发生这种情况.在这里,你不关心代码在所有,但想用你的基础要告诉你的编译器和人人/派生类,这个派生类是一种特殊的,你的基类,它拥有所有的基类的属性,它的行为正是为基类在其用户可见的范围内执行,并且可以在任何算法中使用而不是基类.

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

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.
Run Code Online (Sandbox Code Playgroud)

由于您想要更改接口,因此您不应该使用公共继承,通过更改接口,您可以有效地说这两个类具有不同的行为,并且不能互换使用.所以你真正想要的是私下继承,然后制作你想要公开的所有方法,而不是相反.