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

ここに問題があります。これは、リスコフの置換原則に直接違反することになります。つまり、もはや機能し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がの仮想の削除されていないAメソッドでない場合に機能します。C ++11標準§10.3/16では、派生クラスの削除されたメソッドが基本クラスの仮想の削除されていないメソッドをオーバーライドする場合、この明示的な削除は不正な形式になります。この制限の詳細については、SOの質問C ++ 11 DeleteOverridenMethodへの回答を参照してください。

于 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

作曲を提案している人には...これは物事を進めるための最良の方法ではないかもしれません。私の理解では、リスコフの置換原則は、基本クラスの関数が子で使用される可能性があると述べているだけであり、必ずしもそうあるべきではないということです。たとえば、特定の基本クラスの場合、基本的に同じ操作を実行する複数の関数がありますが、特定のケースが異なります。派生クラスでは、ユーザーのインターフェイスを簡素化するために、これらのパブリック関数を抽象化することができます。これは、プライベート継承を使用できる場所です。基本クラスのユーザーに呼び出させたくない基本クラスの関数を保護しているが、派生クラスにとって非常に貴重な場合は、プライベート継承も必要になる可能性があります。

つまり、必要な場合はプライベート継承を使用しますが、ほとんどの場合、構成が優先されます。

于 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を使用して、望ましくないメソッドを除外します。この場合、BクラスのオブジェクトがBInterfaceクラスのオブジェクトであっても、BInterfaceクラスのオブジェクトはAクラスのオブジェクトではないため、リスコフの置換原則に違反することはありません。

于 2018-02-13T21:20:58.643 に答える
2

メソッドがBでプライベートである場合、パブリック継承を使用しても、メソッドは非表示のままになります。

于 2011-02-05T18:05:22.350 に答える
0

元のメソッドの可視性を変更することはできません。

structに同じ名前のメソッドを作成し、そのメソッドをプライベートにすることもできますが、structのインスタンスがタイプの変数によって参照されているAときにメソッドが呼び出されるのを防ぐことはできません。AB

于 2011-02-05T18:11:18.073 に答える
0

基本クラスでVirtualにして、Childrenでオーバーライドしてみませんか?(より多くのヘルプ

于 2011-02-05T18:12:03.193 に答える