派生クラス関数から親クラス関数を呼び出す方法は?


604

C ++を使用して派生クラスから親関数を呼び出すにはどうすればよいですか?たとえば、というクラスとparentchild親から派生したというクラスがあります。各クラス内にはprint関数があります。子の印刷関数の定義で、親の印刷関数を呼び出したいと思います。これを行うにはどうすればよいですか?


上記のすべてのソリューションは、印刷関数が静的メソッドであることを前提としています。これは事実ですか?メソッドが静的でない場合、上記のソリューションは関係ありません。
hhafez 2008

14
hhafez、base :: function()構文は静的メソッド呼び出し構文のように見えますが、このコンテキストではインスタンスメソッドに対して機能します。
Motti、

2
プラットフォーム固有であるため、MSVC __superは使用しません。他のプラットフォームではコードが実行されない可能性がありますが、意図した言語で実行されるため、他の提案を使用します。
ティーザー


親クラスの関数を呼び出すために派生クラスが常に必要れるアンチパターンはCall super
Rufus

回答:


775

基本的なクラスで定義されている場合は、派生クラスで自動的に使用できるように関数を呼び出します(そうでない場合private)。

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

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'
    }
};

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

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

31
同じクラスから2回継承したいのはなぜですか?
Paul Brewczynski 2013年

65
@bluesm:従来のOOPではあまり意味がありませんが、一般的なプログラミングでtemplate<class A, class B> class C: public A, public B {};は、コードの使用方法に応じて(AとBが同じになる)理由により、2つのタイプが同じになる場合があり、2つまたは3つになる場合があります。あなたがしたことに気づいていない誰かからの抽象化層の方法。
エミリオガラヴァリア2013年

8
私は、これはそれが親クラスに直接実装されていませんが、場合でも、親クラスのメソッドを呼び出すこと、それは追加するのに便利だと思うされ、継承チェーンで親クラスのいずれかで実装されています。
Maxim Lavrov、2014

4
余談ですが、これをcppファイルに入れようとすると、私は怒りました。私は「名前空間stdを使用」していました。「左」はその名前空間のどこかに定義されています。例はコンパイルされません-私を狂わせました:)。次に、「左」を「左」に変更しました。ちなみに素晴らしい例です。
マタイ2015

72
@Mathaiそして、それがあなたが使用することになっていない理由ですusing namespace std
JAB

193

という名前の親クラスとという名前のParent子クラスがChildある場合、次のようなことができます。

class Parent {
public:
    virtual 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はクラスの実際の名前であり、キーワードではないことに注意してください。


もちろん、これはベースコールが他のロジックに散在している場合にのみ役立ちます。それ以外の場合は、関数をオーバーライドしても意味がありません。そのため、多分少なすぎます;)
underscore_d

1
@underscore_dは、実際には、ベースコールが他のロジックに散在していなくても役立ちます。親クラスがほとんどすべてのことを実行するとしますが、子のユーザーに使用してほしくないメソッドfoo()を公開します-foo()が子で無意味であるか、子への外部の呼び出し元が子を混乱させるためですやっている。したがって、子は特定の状況でparent :: foo()を使用できますが、fooの実装を提供して、親のfoo()が呼び出されないようにします。
iheanyi

@iheanyi面白そうですが、申し訳ありませんが、まだ把握していません。であるfoo()と類似し、ここでprint()または別の機能?そして、private継承を使用してベースから継承された詳細を非表示にし、公開たいpublicものにシャドウ機能を提供するということですか?
underscore_d

@underscore_dはい、foo()に似ていましたprint()print()このコンテキストではより理にかなっていると思うので、使用に戻りましょう。誰かが特定のデータ型に対して一連の操作を実行するクラスを作成し、いくつかのアクセサを公開し、print(obj&)メソッドを持っているとしましょう。動作する新しいクラスが必要array-of-objですが、他のすべては同じです。構成により、多くのコードが重複します。継承により、print(array-of-obj&) ループ呼び出しprint(obj&)でそれが最小限に抑えられますが、クライアントには呼び出しprint(obj&)が意味をなさないため、呼び出しを望まないのです
iheanyi

@underscore_dこれは、元の親クラスの共通部分をリファクタリングできないか、そうすると信じられないほどコストがかかるという前提に基づいています。プライベート継承は機能しますが、依存していたパブリックアクセサーが失われるため、コードを複製する必要があります。
iheanyi

32

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

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

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

28

MSVCにはそのためのMicrosoft固有のキーワードがあります:__super


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)
   }
};


5
ええと、私typdefは親のようなものを好むでしょうsuper
Thomas Eding、2011年

26
私はの使用を正当化しようとはしません__super。ここでは、代替案として言及しました。開発者はコンパイラを理解し、その機能の長所と短所を理解する必要があります。
Andrey

13
コードの移植性を著しく妨げるので、だれもそれを使用しないようにしてください。
Erburethはモニカを

26
Andreyに同意しません。開発者は標準を知っている必要があり、コンパイラー機能に煩わされる必要はありません。主にコンパイラーに依存しないソフトウェアを書くことを検討する場合は、いずれにせよ、大規模なプロジェクトで複数のコンパイラーを使用することをお勧めします。とにかく使われています。
ガブリエル14

7
「開発者はコンパイラを知っている必要があります」この推論と非標準機能の組み込みがIE6につながったのです...
e2-e4

5

基本クラスのメンバー関数のアクセス修飾子が保護されているか、パブリックである場合、派生クラスから基本クラスのメンバー関数を呼び出すことができます。派生メンバー関数から基本クラスの非仮想メンバー関数と仮想メンバー関数を呼び出すことができます。プログラムを参照してください。

#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

1
でいくつかの例を紹介していただきありがとうございますvirtual
M.Ioan

5

親スコープ解決演算子を使用して親メソッドを呼び出します。

Parent :: method()

class Primate {
public:
    void whatAmI(){
        cout << "I am of Primate order";
    }
};

class Human : public Primate{
public:
    void whatAmI(){
        cout << "I am of Human species";
    }
    void whatIsMyOrder(){
        Primate::whatAmI(); // <-- SCOPE RESOLUTION OPERATOR
    }
};

-15
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();
}

参考例。


2
このコードがなぜ/どのように質問に答えるかの説明を編集していただけませんか?コードのみの回答は、説明付きのコードほど簡単に学ぶことができないため、お勧めしません。説明がなければ、何が行われていたか、コードに加えられた変更、またはコードが有用かどうかを理解するには、かなり多くの時間と労力が必要です。説明は、回答から学習しようとする人と、回答が有効かどうか、または投票する価値があるかどうかを確認するために回答を評価する人の両方にとって重要です。
Makyen

3
この回答はネストされたクラスに関するものであり、質問は派生クラスに関するものでしたが(「親」と「子」という言葉は少し誤解を招くかもしれませんが)、質問にはまったく答えません。
Johannes Matokic
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.