489

C ++を使用して派生クラスから親関数を呼び出す方法たとえば、私はと呼ばれるクラスがありますparentと呼ばれるクラスchildこれは親から派生しています。内に 各クラスがありますprint関数。子供の印刷機能の定義で、私は両親の印刷機能を呼び出したいと思います。これをどのようにして行うのでしょうか。


  • 上記のすべての解決策はあなたのprint関数が静的メソッドであると仮定しています。これは事実ですか?方法が静的でない場合、上記の解決策は関係ありません。 - hhafez
  • hhafezさん、base :: function()の文法は静的メソッド呼び出しの文法のようですが、この文脈ではインスタンスメソッドのために動作します。 - Motti
  • プラットフォーム固有のMSVCスーパーを使用しないでください。あなたのコードは他のどのプラットフォームでも動かないかもしれませんが、彼らは意図した言語としてそれをするので私は他の提案を使用します。 - Teaser
  • の可能な重複オーバーライドしている場合は、基本クラスの仮想関数を呼び出すことはできますか。 - Archmede

6 답변


629

私は明白なことを述べる危険性を冒します:あなたがその関数を基本クラスで定義されているなら、あなたはそれが派生クラスで自動的に利用可能であると呼びますprivate

派生クラスに同じシグネチャを持つ関数がある場合は、基本クラスの名前とそれに続く2つのコロンを追加することによってそれを明確にすることができます。base_class::foo(...)。 JavaやC#とは異なり、C ++では機能します。ではない「基本クラス」のキーワードがある(superまたはbaseC + +をサポートしているため)多重継承あいまいさにつながる可能性があります。

class left {
public:
    void foo();
};

class right {
public:
    void foo();
};

class bottom : public left, public right {
public:
    void foo()
    {
        //base::foo();// ambiguous
        left::foo();
        right::foo();

        // and when foo() is not called for 'this':
        bottom b;
        b.left::foo();  // calls b.foo() from 'left'
        b.right::foo();  // call b.foo() from 'right'
    }
};

ちなみに、同じクラスから直接2回派生させることはできません。基本クラスの1つを他のクラスから参照する方法がないからです。

class bottom : public left, public left { // Illegal
};


  • 同じクラスから2回継承したいのはなぜですか? - Paul Brewczynski
  • @bluesm:古典的なOOPでは意味がありませんが、ジェネリックプログラミングではtemplate<class A, class B> class C: public A, public B {};コードの使い方(AとBを同じにする)に応じて、2つのタイプが同じ理由で同じになることがあります。 - Emilio Garavaglia
  • 親クラスに直接実装されていなくても、これが親クラスのメソッドを呼び出すことを追加するのが便利だと思いますが、です継承チェーンの親クラスの1つに実装されています。 - Maxim Lavrov
  • 傍観者として、これをcppファイルに書き込もうとしたときに気が狂った。名前空間stdを使用しています。 '左'その名前空間のどこかで定義されている。例ではコンパイルできませんでした - おかしくなりました:)。それから私は'左'を変更しました'左へ'ところで素晴らしい例です。 - Mathai
  • @Mathaiそれが、あなたが使うべきではない理由です。using namespace std。 - JAB

166

指定された親クラスParentという名前の子クラスChildあなたはこのようなことをすることができます:

class Parent {
public:
    void print(int x);
}

class Child : public Parent {
    void print(int x) override;
}

void Parent::print(int x) {
    // some default behavior
}

void Child::print(int x) {
    // use Parent's print method; implicitly passes 'this' to Parent::print
    Parent::print(x);
}

ご了承くださいParentクラスの実際の名前であり、キーワードではありません。


  • なぜこのアナラーはこれほど多くの支持を得ているのですか? C ++でこれがどのように行われるのかわかりません。 - ancajic
  • @ancajic:質問からのクラスの名前を使って、parent親クラスの実際の名前です。親クラスが呼び出された場合widgetそれならあなたは電話するでしょうwidget::print(x);。 - Greg Hewgill
  • もちろん、これは基本呼び出しが他のロジックと混在している場合にのみ役に立ちます。そうでなければ、関数をオーバーライドしても意味がありませんので、ちょっとだけかもしれません。ポイントへ ;) - underscore_d
  • @underscore_dは実際には、ベースコールが他のロジックと混在していなくても役に立ちます。親クラスがほとんどすべてのことを実行するとしましょうが、foo()メソッドを公開します。ただし、foo()は子供や外部の呼び出し元では意味がありません。子供がしていることを台無しにするでしょう。そのため、childは特定の状況でparent :: foo()を使用することがありますが、親のfoo()が呼び出されないようにfooの実装を提供します。 - iheanyi
  • @ iheanyi面白そうですが、すみません、まだ理解できていません。ですfoo()ここに類似したprint()それとも別の機能?そして使うということですかprivateベースから継承された詳細を隠すための継承publicあなたのためのシャドウイング関数行う公開したいですか? - underscore_d

28

基本クラスが呼び出された場合Baseそしてあなたの関数は呼ばれますFooBar()あなたはそれを使用して直接それを呼び出すことができますBase::FooBar()

void Base::FooBar()
{
   printf("in Base\n");
}

void ChildOfBase::FooBar()
{
  Base::FooBar();
}


20

MSVCには、そのためのMicrosoft固有のキーワードがあります。__スーパー


MSDN: オーバーライドしている関数に対して基本クラスの実装を呼び出していることを明示的に示すことができます。

// deriv_super.cpp
// compile with: /c
struct B1 {
   void mf(int) {}
};

struct B2 {
   void mf(short) {}

   void mf(char) {}
};

struct D : B1, B2 {
   void mf(short) {
      __super::mf(1);   // Calls B1::mf(int)
      __super::mf('s');   // Calls B2::mf(char)
   }
};


  • ええ、私は好きですtypdef親のようなものとしてsuper。 - Thomas Eding
  • の使用法を正当化しようとしませんでした__super;私はそれを別の提案としてここで述べました。開発者は自分のコンパイラを知っていて、その機能の長所と短所を理解する必要があります。 - Andrey
  • コードの移植性を著しく妨げるため、だれかがそれを使用するのをやめさせることをお勧めします。 - Erbureth
  • Andreyには賛成できません。開発者は標準を知っている必要があり、コンパイラーの機能に煩わされる必要はありません。大規模プロジェクトでは遅かれ早かれ私はとにかくいい考えだと思います。とにかく複数のコンパイラが使用されています。 - Gabriel
  • "開発者は自分のコンパイラを知っている必要があります"この推論、そして非標準的な機能の包含は、IE6につながったものです... - Ring Ø

3

基本クラスメンバ関数のアクセス修飾子がprotectedまたはpublicの場合、派生クラスから基本クラスのメンバ関数を呼び出すことができます。 派生メンバ関数から基本クラスの非仮想および仮想メンバ関数を呼び出すことができます。 プログラムを参照してください。

#include<iostream>
using namespace std;

class Parent
{
  protected:
    virtual void fun(int i)
    {
      cout<<"Parent::fun functionality write here"<<endl;
    }
    void fun1(int i)
    {
      cout<<"Parent::fun1 functionality write here"<<endl;
    }
    void fun2()
    {

      cout<<"Parent::fun3 functionality write here"<<endl;
    }

};

class Child:public Parent
{
  public:
    virtual void fun(int i)
    {
      cout<<"Child::fun partial functionality write here"<<endl;
      Parent::fun(++i);
      Parent::fun2();
    }
    void fun1(int i)
    {
      cout<<"Child::fun1 partial functionality write here"<<endl;
      Parent::fun1(++i);
    }

};
int main()
{
   Child d1;
   d1.fun(1);
   d1.fun1(2);
   return 0;
}

出力:

$ g++ base_function_call_from_derived.cpp
$ ./a.out 
Child::fun partial functionality write here
Parent::fun functionality write here
Parent::fun3 functionality write here
Child::fun1 partial functionality write here
Parent::fun1 functionality write here


-12

struct a{
 int x;

 struct son{
  a* _parent;
  void test(){
   _parent->x=1; //success
  }
 }_son;

 }_a;

int main(){
 _a._son._parent=&_a;
 _a._son.test();
}

参考例です。


  • して頂けますか編集するなぜこのコードが質問に答えるのか、その方法の説明には?コードのみの回答は、説明付きのコードほど簡単に習得できないため、お勧めできません。説明がないと、行われていたこと、コードに加えられた変更、またはコードが有用かどうかを理解するのにかなり時間と労力がかかります。答えから学ぶことを試みる人々とそれが有効であるかどうかを確かめるために答えを評価する人々、または投票する価値がある人々の両方にとって、説明は重要です。 - Makyen
  • 派生クラスに関する質問であったのに対し、この回答は入れ子になったクラスに関するもので(< parent'という単語は少し誤解を招く可能性がありますが)、したがって質問には回答しません。まったく - Johannes Matokic

リンクされた質問


関連する質問

最近の質問