用c ++隐藏特定函数的方法

lur*_*her 21 c++ inheritance using private-members public-fields

我有一个继承struct A : public B,我想隐藏B的个别功能,这可能吗?

我知道using BMethod在A声明中可以使用相反的方法.

干杯

Eug*_*nca 43

如果你想有选择地隐藏B中的函数,那么首先使用公共继承没有多大意义.
使用私有继承并有选择地将B中的方法引入A的范围:

struct B{
   void method1(){};
   void method2(){};
};
struct A : private B{
   using B::method1;
};

A a;
a.method1();
a.method2(); //error method2 is not accesible
Run Code Online (Sandbox Code Playgroud)


Mat*_* M. 25

这里存在一个问题:这将直接违反利斯科夫替代原则,即A不再采取行动 B.

如果您希望重用B实现,解决方案就是这样做:

class A
{
public:
  void foo() { return b.foo(); }
  void bar() { return b.bar(); }
  // ...

private:
  B b;
};
Run Code Online (Sandbox Code Playgroud)

不要滥用继承,而是使用组合

  • 恰好必须编写一个99%的另一个类的类,但处理不同的东西并且有1个函数,只有一个函数在B中不存在. (5认同)
  • 这不一定是继承滥用,它只是意味着 B 不是 A 的子类型(如公共继承中那样),但 B 是根据 A 实现的,因此 LSP 不受影响。我相信“使用组合代替”通常是一个很好的建议,但是非公共继承可以是实现外观模式的有用工具,即看看 javax.swing.JButton 是多么臃肿。 (2认同)

Cod*_*cks 12

除了前面的答案 - 组合,私有继承和非私有继承中描述的方式,但是声明为private的继承方法 - 另一种方式是显式delete继承的方法:

#include <iostream>

struct A {
    void foo() { std::cout << "foo\n"; }
};

struct B : A {
    void foo() = delete;
};

int main() {
    B b;
    b.foo(); // COMPILER ERROR
}
Run Code Online (Sandbox Code Playgroud)

虽然b.foo()调用产生编译器错误,但客户端代码仍然可以通过使用基类标识符进行限定来调用基类的版本A:

b.A::foo(); // compiles, outputs 'foo' to console
Run Code Online (Sandbox Code Playgroud)

当这种显式删除的工作方式foo不是在一个虚拟的非删除方法A.通过C++ 11标准§10.3/ 16,当派生类中的deleted方法覆盖基类的虚拟未删除方法时,此显式删除是不正确的.有关此限制的更多信息,请参阅SO问题C++ 11删除Overriden方法的答案.


Bil*_*eal 8

你不能"隐藏它"本身,但你可以把它编成一个编译时错误来调用它.例:

struct A
{
    void AMethod() {}
};

class B : public A
{
    void AMethod() {} //Hides A::AMethod
};

int main()
{
    B myB;
    myB.AMethod(); //Error: AMethod is private
    static_cast<A*>(&myB)->AMethod(); //Ok
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

有错误的键盘上的示例,没有.

尽管如此,尽管如此,你真的不应该这样做.你会混淆客户的地狱.

编辑:请注意,您也可以使用虚函数(以及错误)执行此操作.


xav*_*sjs 6

using关键字可以用来改变的可视性

struct A
{
    void method1();
};

struct B: public A
{
    void method2();

    private:
    using A::method1;
};
Run Code Online (Sandbox Code Playgroud)