489

C ++을 사용하여 파생 클래스에서 부모 함수를 어떻게 호출합니까? 예를 들어 나는 클래스를 호출했다.parent, 그리고 클래스 호출child부모로부터 파생 된 이내에 각 반에는print기능. 자식의 인쇄 함수 정의에서 부모 인쇄 함수를 호출하고 싶습니다. 이 일을 어떻게 하죠?


  • 위의 모든 솔루션은 인쇄 기능이 정적 방법이라고 가정합니다. 이 경우인가요? 메서드가 정적이 아닌 경우 위의 해결 방법은 적합하지 않습니다. - hhafez
  • hhafez, 당신은 base :: function () 구문은 정적 메소드 호출 구문처럼 보이지만이 컨텍스트의 인스턴스 메소드에서는 작동한다고 착각했습니다. - Motti
  • MSVC __super는 특정 플랫폼에서만 사용할 수 있습니다. 코드가 다른 플랫폼에서 실행되지 않을 수도 있지만 다른 언어는 의도 한대로 사용하므로 다른 제안을 사용합니다. - Teaser
  • 가능한 중복기본 클래스의 가상 함수를 재정의하면 기본 함수의 가상 함수를 호출 할 수 있습니까? - Archmede

6 답변


629

나는 명백한 것의 위험을 감수 할 것이다 : 함수를 호출한다. 기본 클래스에 정의되어 있다면 파생 클래스에서 자동으로 사용할 수있다.private).

파생 클래스에 동일한 시그니처가있는 함수가 있으면 기본 클래스의 이름 뒤에 두 개의 콜론을 추가하여 명확하게 할 수 있습니다base_class::foo(...). Java 및 C #과 달리 C ++는아니"기본 클래스"에 대한 키워드를 가지고있다 (super또는base) C ++가 지원하기 때문에다중 상속모호함을 초래할 수 있습니다.

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

덧붙여 말하면, 기본 클래스 중 하나를 다른 클래스보다 참조 할 방법이 없으므로 동일한 클래스에서 두 번 직접 파생시킬 수 없습니다.

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


  • 왜 같은 반에서 두 번 상속 받고 싶니? - Paul Brewczynski
  • @ bluesm : 고전적인 OOP에서는 의미가 없지만 일반적인 프로그래밍template<class A, class B> class C: public A, public B {};코드가 사용되는 방식에 따라 두 가지 유형이 동일 할 수 있습니다 (즉, A와 B가 같아집니다). 사용자가 수행 한 작업을 인식하지 못하는 사람들로부터 2 ~ 3 가지 추상화 계층 방식이 될 수 있습니다. - Emilio Garavaglia
  • 추가하는 것이 유용하다고 생각합니다. 부모 클래스에서 직접 구현되지 않더라도 부모 클래스 메서드를 호출하지만~이다.상속 체인의 부모 클래스 중 하나에서 구현됩니다. - Maxim Lavrov
  • sidenote에서이 파일을 cpp 파일에 넣으려고하면 화를 냈습니다. 네임 스페이스 표준을 사용하고 있습니다. ' ' 왼쪽 ' 해당 네임 스페이스의 어딘가에 정의됩니다. 예제는 컴파일되지 않을 것입니다 - 나를 미치게했습니다 :). 그런 다음   왼쪽 ' 왼쪽으로 ' 그 좋은 예입니다. - 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클래스의 실제 이름이며 키워드가 아닙니다.


  • 이 anwer에는 왜 많은 upvotes가 있는가? 이것이 C ++에서 어떻게 수행되는지는 알 수 없습니다. - ancajic
  • @ancajic : 질문의 클래스 이름을 사용하여,parent부모 클래스의 실제 이름입니다. 부모 클래스가 호출 된 경우widget, 그러면 당신은 전화 할 것입니다.widget::print(x);. - Greg Hewgill
  • 물론 이것은 기본 호출이 다른 로직과 흩어져있는 경우에만 유용 할 것입니다. 그렇지 않으면 함수를 재정의하는 데 아무런 소용이 없으므로 아마도 약간의너무to-the-point;) - underscore_d
  • @underscore_d는 실제로 기본 호출이 다른 논리에 흩어져 있지 않은 경우에도 유용합니다. 부모 클래스가 원하는 모든 것을 거의 수행한다고 가정 해 보겠습니다. foo ()가 자식 또는 외부 호출자에서 의미가 없기 때문에 자식의 사용자가 사용하지 못하도록하려는 foo () 메서드를 제공합니다. 아이가하고있는 것을 망칠 것입니다. 따라서 특정 상황에서는 parent :: foo ()를 사용할 수 있지만 부모의 foo ()가 호출되지 않도록 foo의 구현을 제공합니다. - 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

기본 클래스 멤버 함수의 접근 한정자가 public 또는 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
  • 이 답변은 중첩 된 클래스에 대한 것이지만 질문은 파생 클래스에 관한 것이지만 (단어 '부모'와 '자녀'는 약간 미혹 될 수 있지만) 질문에 대한 답변을 제공하지 않습니다. 조금도. - Johannes Matokic

연결된 질문


관련된 질문

최근 질문