[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jfriends-ml 12251] C++ の public 継承と private 継承



こんばんは遠藤です。

今日出てきたC++のpublic継承とprivate継承ですが
特にprivateの方はJavaにはない機能なのでご説明します。

まずpublic継承の方は、Javaの継承とほぼ同様です。
たとえば、Javaで
class A {
  public void foo() {}
}

class B extends A {
  public void bar() {}
}

と書くのは、C++のpublic継承を使って

class A {
public:
  void foo() {
      printf("foo called\n\n");
  }
};

class B: public A { //継承の時に"public"を指定している
public:
  void bar() {
      printf("calling foo()\n");
      foo(); //Aから継承したメソッドをBから呼ぶ
  }
};


と書くのとほぼ同様で
int main(int argc, char *argv[]) {
  B* b = new B();
  b->bar();

  b->foo(); //Aから継承したメソッドを外から呼ぶ	
  A *a = b; //B型のオブジェクトを、A型として扱う

  delete b;
}
のように使えます。


Aをpublic継承するということは、
Aから継承したものを、Aとそのまま公開しているので
「publicな継承」と解釈できます。


一方で、private継承ですが、

Aは同じとして、継承の際にprivateを指定するのだけ変えます。

class B: private A { //継承の時にprivateを指定している
public:
  void bar() {
      printf("calling foo()\n");
      foo(); //これはOK
             //privateフィールドのpublicメソッドにアクセスできるのと同様
  }
};

int main(int argc, char *argv[]) {
  B* b = new B();
  b->bar();

  b->foo(); // コンパイルエラー
  A *a = b; // コンパイルエラー
            // BがAを継承しているのは、"private"なので
            // 外からAのメソッドにアクセスしたり、
            // A型のポインタに代入できない
            // g++では `A' is an inaccessible base of `B' と表示される
  delete b;
}


のように
1. Bクラスの中から、Aのpublicメソッドにはアクセスできる
2. Bクラスの外では、Aのpublicメソッドにアクセスできない
となります。


この2番目の、特徴は不便なように思えるかも知れませんが
実際には、
Aを継承していることを、外部には隠すことができる
と解釈すると

Bは、Aの実装を継承して使いたいが、
Aのpublicメソッドを、B型としては公開したくない。

というケースで使うことができます。

今日出てきたAdapterパターンでは、
Adapterは、Adapteeの実装を継承して使いたいが、
Adapteeのpublicメソッドを、Adapter型としては公開したくない。
ので、private継承を使うという説明でした。



-- 
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
遠藤 康裕  quiver2k@xxxxxxxxx
_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/


#include <stdio.h>

class A {
public:
  void foo() {
      printf("foo called\n\n");
  }
};

class B: private A {
public:
  void bar() {
      printf("calling foo()\n");
      foo(); //A‚©‚çŒp³‚µ‚½ƒƒ\ƒbƒh‚ðB‚©‚çŒÄ‚Ô
  }
};

int main(int argc, char *argv[]) {
  B* b = new B();
  b->bar();

//  b->foo(); //A‚©‚çŒp³‚µ‚½ƒƒ\ƒbƒh‚ðŠO‚©‚çŒÄ‚Ô
//  A *a = b; //BŒ^‚̃IƒuƒWƒFƒNƒg‚ðAAŒ^‚Æ‚µ‚Ĉµ‚¤

  delete b;
}