파생 클래스 함수에서 부모 클래스 함수를 호출하는 방법은 무엇입니까?


603

C ++를 사용하여 파생 클래스에서 부모 함수를 어떻게 호출합니까? 예를 들어,이라는 클래스 parentchildparent에서 파생 된 클래스 가 있습니다. 각 클래스에는 print기능이 있습니다. 자녀의 인쇄 기능 정의에서 부모 인쇄 기능을 호출하고 싶습니다. 어떻게하면 되나요?


위의 모든 해결책은 인쇄 기능이 정적 방법이라고 가정합니다. 이 경우입니까? 방법이 정적이 아닌 경우 위의 솔루션은 관련이 없습니다.
hhafez

14
hhafez, base :: function () 구문은 정적 메소드 호출 구문처럼 보이지만이 컨텍스트의 인스턴스 메소드에서 작동합니다.
Motti

2
플랫폼에 따라 다르므로 MSVC __super를 사용하지 않습니다. 코드가 다른 플랫폼에서 실행되지 않을 수도 있지만 다른 제안 사항은 의도 한 언어로 수행되므로 다른 제안을 사용합니다.
Teaser


파생 클래스가 항상 부모 클래스 함수를 호출 해야하는 반 패턴 은 Call super
Rufus

답변:


775

기본 클래스에 정의 된 함수는 파생 클래스에서 자동으로 사용할 수 있습니다 (이 아닌 경우 private).

파생 클래스에 동일한 서명을 가진 함수가있는 경우 기본 클래스 이름 뒤에 두 개의 콜론을 추가하여 명확하게 표시 할 수 있습니다 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'
    }
};

또한 기본 클래스 중 하나를 다른 클래스보다 참조 할 수있는 방법이 없으므로 동일한 클래스에서 직접 두 번 파생 할 수 없습니다.

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

30
왜 같은 클래스에서 두 번 상속하고 싶습니까?
Paul Brewczynski

65
@ bluesm : 고전적인 OOP에서는별로 의미가 없지만 일반 프로그래밍 template<class A, class B> class C: public A, public B {};에서는 코드 사용 방식에 따라 두 가지 유형이 동일 할 수 있습니다 (A와 B를 동일하게 만듭니다). 당신이 한 일을 모르는 누군가의 추상화 계층 방법.
Emilio Garavaglia

8
나는이가 부모 클래스에서 직접 구현되지 않은 경우에도 부모 클래스의 메소드를 호출 것을 추가하는 것이 유용하지만 생각 되는 상속 체인에서 부모 클래스 중 하나에서 구현.
Maxim Lavrov

4
참고로, 이것을 cpp 파일에 넣으려고 할 때 화를 냈습니다. '사용 네임 스페이스 std'가있었습니다. 'left'는 해당 네임 스페이스의 어딘가에 정의되어 있습니다. 이 예제는 컴파일되지 않았으며 나를 미치게했습니다 :). 그런 다음 '왼쪽'을 '왼쪽'으로 변경했습니다. 그건 그렇고 좋은 예입니다.
Mathai

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 () 메소드를 노출한다고 가정 해보십시오. 하기. 따라서 자식은 특정 상황에서 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.
토마스 대한 수정 사항

26
나는 사용법을 정당화하려고하지 않을 것이다 __super. 대체 제안으로 여기에 언급했습니다. 개발자는 컴파일러를 알고 해당 기능의 장단점을 이해해야합니다.
Andrey

13
코드의 이식성을 심각하게 방해하므로 다른 사람이 사용하지 않는 것이 좋습니다.
Erbureth는 Reinstate Monica가

26
Andrey와 동의하지 않습니다. 개발자가 표준을 알고 있어야하며 컴파일러 기능에 신경 쓸 필요가 없습니다. 주로 컴파일러와 독립적 인 소프트웨어를 작성하는 것을 고려한다면 어쨌든 큰 프로젝트에서 여러 컴파일러 때문에 좋은 아이디어라고 생각합니다 어쨌든 사용됩니다.
Gabriel

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

부모 범위 확인 연산자를 사용하여 부모 메서드를 호출하십시오.

부모 :: 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.