25

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

using BMethod我知道在 A 声明中使用相反的情况是可能的。

干杯

4

10 回答 10

55

如果您想有选择地对 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
于 2011-02-05T18:14:56.257 回答
30

这里有一个问题:这将直接违反 Liskov 替换原则,即A不再充当 B

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

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

private:
  B b;
};

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

于 2011-02-05T18:25:44.273 回答
23

关键字可using用于更改可见性

struct A
{
    void method1();
};

struct B: public A
{
    void method2();

    private:
    using A::method1;
};
于 2018-11-30T23:16:21.597 回答
15

除了前面的答案中描述的方式——组合、私有继承和非私有继承,但继承的方法声明为私有——另一种方法是显式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
}

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

b.A::foo(); // compiles, outputs 'foo' to console

这种显式删除方式在foo不是. 根据 C++11 标准 §10.3/16,当派生类中的已删除方法覆盖基类的虚拟未删除方法时,此显式删除是错误的。有关此限制的更多信息,请参阅 SO 问题C++11 Delete Overriden Method的答案。A

于 2014-10-30T23:55:23.217 回答
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;
}

有错误没有错误的键盘示例。

话虽如此,尽管这是可能的,但您确实不应该这样做。你会把客户搞糊涂的。

编辑:请注意,您也可以使用虚函数(并且带有错误)来执行此操作。

于 2011-02-05T18:08:10.590 回答
4

对于那些建议组合的人......这可能不是最好的处理方式。我的理解是,Liskov 替换原则仅说明基类中的函数有可能用于子类,而不是它们必须如此。例如,对于特定的基类,您可能有多个函数,它们基本上执行相同的操作,但针对不同的特定情况。在派生类中,您可能希望将这些公共函数抽象出来,以简化用户界面。这是可以使用私有继承的地方。私有继承也可能是必要的,如果我们在基类中有受保护的函数,我们不希望基类的用户调用,但对于派生类来说是无价的。

简而言之,如果必须,请使用私有继承,但在大多数情况下首选组合。

于 2013-06-06T03:07:40.713 回答
3

还有另一种方法。

class A{
    void f1();
    void f2();
    void f3();
}

class BInterface{
    void f2();
    void f3();
}

class B : public A, BInterface
{
}

BInterface b = new B();
b->f1(); //doesn't work since f1 is not declared in BInterface
b->f2(); //should work
b->f3(); //should work
delete(b);

使用 BInterface 作为继承类的过滤器以排除不需要的方法。在这种情况下不违反里氏替换原则,因为 BInterface 类的对象不是 A 类的对象,即使 B 类的对象是 BInterface 类的对象。

于 2018-02-13T21:20:58.643 回答
2

如果方法在 B 中是私有的,那么即使您使用公共继承,它们也会对 a 保持隐藏。

于 2011-02-05T18:05:22.350 回答
0

无法更改原始方法的可见性。

您可以在 struct 中创建一个A具有相同名称的方法并将该方法设为私有,但这并不妨碍在 struct 的实例A被类型变量引用时调用该方法B

于 2011-02-05T18:11:18.073 回答
0

为什么不在基类中将其设为虚拟并在其子类中覆盖它?(更多帮助

于 2011-02-05T18:12:03.193 回答