33

次のスニペットを検討してください。

struct Base
{
  virtual ~Base() {}

  virtual void Foo() const = 0; // Public
};

class Child : public Base
{
  virtual void Foo() const {} // Private
};

int main()
{
  Child child;

  child.Foo(); // Won't work. Foo is private in this context.

  static_cast<Base&> (child).Foo(); // Okay. Foo is public in this context.
}

これは正当な C++ ですか? 「これ」は、派生クラスで仮想関数のアクセス モードを変更しています。

4

4 に答える 4

21

これは正当な C++ であり、§11.6/1 は次のように述べています。

アクセスは、メンバー関数が呼び出されるオブジェクトを示すために使用される式の型 (上の例では B*) を使用して、呼び出しポイントでチェックされます。メンバー関数が定義されたクラス (上記の例では D) でのメンバー関数のアクセスは、一般に不明です。

あなたが指摘しChild::Foo()たように、基本クラスを介して引き続きアクセスできますが、これはほとんどの場合望ましくありません。

 Child* c = new Child;
 Base* b = c;
 c->Foo(); // doesn't work, Child::Foo() is private
 b->Foo(); // works, calls Child::Foo()

基本的に、式で参照する宣言はアクセスモードを決定しますが、仮想関数は別の関数としてそれを弱体化させ、名前付き関数が実際に呼び出される可能性があります。

于 2010-01-26T17:57:10.260 に答える
20

Yes, changing the access mode in derived classes is legal.

This is similar in form but different in intent to the Non-Virtual Interface idiom. Some rationale is given here:

The point is that virtual functions exist to allow customization; unless they also need to be invoked directly from within derived classes' code, there's no need to ever make them anything but private.

As to why you would actually make something public in base but private in derived without private or protected inheritance is beyond me.

于 2010-01-26T17:40:50.890 に答える
5

これは完全に正当な C++ です。Child クラスで新しいメソッドを定義しているだけです。

今、それはあなたがしたいことをしますか、それは別の問題です。アクセス モードはメソッド シグネチャの一部ではないと思います。つまり、Base の Foo 仮想メソッドを呼び出すと、最終的に Child の Foo メソッドが呼び出されます。

結論は次のとおりです。これは正当な C++ であり、期待どおりに動作します。

child.Foo();Child のプライベート Foo() メソッドにアクセスしようとしていることは間違いないため、機能しない行は考慮していません。

于 2010-01-26T17:27:55.553 に答える
4

正しいメソッドをコンパイルして呼び出すようです。

アクセス指定子は、訓練されたプログラマーを支援するために存在することを忘れないでください。アクセス指定子を回避しようとするすべての試みをすべての犠牲を払って防ぐためではありません。

この特定のケースでは、Child はオーバーライドされた仮想関数を非公開にする必要はありません。つまり、Base のパブリック インターフェイスを実装することになっていないので、「is-a」関係が成り立つのでしょうか? (「子はベース」を意味するパブリック継承を使用しなかった場合、あなたのトリックは機能しません。)

于 2010-01-26T17:33:00.310 に答える