Как вызвать функцию родительского класса из производной функции класса?

445

Как вызвать родительскую функцию из производного класса с помощью С++? Например, у меня есть класс под названием parent и класс под названием child, который является производным от родителя. В каждый класс имеет функцию print. В определении дочерней функции печати я хотел бы сделать вызов функции печати родителей. Как я могу это сделать?

  • 0
    Все вышеприведенные решения предполагают, что ваша функция печати является статическим методом. Это тот случай? Если метод не является статичным, то приведенные выше решения не актуальны.
  • 11
    hhafez, вы ошибаетесь, синтаксис base :: function () выглядит как статический синтаксис вызова метода, но он работает для методов экземпляра в этом контексте.
Показать ещё 3 комментария
Теги:
oop
inheritance

6 ответов

607
Лучший ответ

Я рискну заявить очевидное: вы вызываете функцию, если она определена в базовом классе, она автоматически доступна в производном классе (если только не private).

Если в производном классе есть функция с той же сигнатурой, вы можете устранить ее, добавив имя базового класса, за которым следуют два двоеточия base_class::foo(...). Следует отметить, что в отличие от Java и С#, С++ имеет не ключевое слово для "базового класса" (super или base), поскольку С++ поддерживает множественное наследование, которое может привести к двусмысленности.

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
};
  • 24
    Почему вы хотели бы наследовать от одного и того же класса дважды?
  • 51
    @bluesm: в классическом ООП это не имеет особого смысла, но в универсальном template<class A, class B> class C: public A, public B {}; программирования template<class A, class B> class C: public A, public B {}; может относиться к двум типам, являющимся одинаковыми по причинам, зависящим от того, как используется ваш код (что делает А и В одинаковыми), может быть два или три уровня абстракции от кого-то, кто не знает, что вы сделали.
Показать ещё 8 комментариев
152

Учитывая родительский класс с именем 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 print method; implicitly passes 'this' to Parent::print
    Parent::print(x);
}

Обратите внимание, что Parent - это фактическое имя класса, а не ключевое слово.

  • 3
    Почему этот ответ имеет так много голосов? Я не понимаю, как это можно сделать в C ++.
  • 13
    @ancajic: Используя имена классов из вопроса, parent является фактическим именем родительского класса. Если родительский класс был назван widget , то вы бы вызвали widget::print(x); ,
Показать ещё 7 комментариев
28

Если ваш базовый класс называется Base, и ваша функция называется FooBar(), вы можете вызвать ее напрямую, используя Base::FooBar()

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

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

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

  • 3
    Это работает, если функции тоже виртуальные. Хороший совет.
  • 5
    Эх, я бы предпочел typdef родителя как что-то вроде super .
Показать ещё 9 комментариев
3

Если модификатор доступа функции-члена базового класса защищен или открыт, вы можете выполнить функцию-член вызова базового класса из производного класса. Можно вызвать вызов не виртуальной и виртуальной функции-члена базового класса из производной функции-члена. Пожалуйста, обратитесь к программе.

#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
-11
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
    Не могли бы вы отредактировать объяснение, почему / как этот код отвечает на вопрос? Ответы только на код не приветствуются, потому что их не так легко выучить, как код с объяснением. Без объяснения требуется гораздо больше времени и усилий, чтобы понять, что было сделано, изменения, внесенные в код, или, если код полезен. Объяснение важно как для людей, пытающихся извлечь уроки из ответа, так и для тех, кто оценивает ответ, чтобы понять, является ли он действительным или стоит голосовать.
  • 1
    Этот ответ касается вложенных классов, тогда как вопрос был о производных классах (хотя слова 'parent' и 'child' немного вводят в заблуждение) и поэтому вообще не отвечает на вопрос.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню