English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Подробное объяснение наследования в C++ и примеры кода

 Inheritance в C++ может быть одноуровневой или многоуровневой, каждый уровень наследования может быть public, protected, private, а также virtual или non-virtual. Затем для каждого члена функции можно выбрать virtual, non-virtual или pure virtual. В этой статье рассматриваются только ключевые моменты.

  public inheritance, например, как показано ниже:

1 class base
2 {...}
3 class derived:public base
4 {...}

  Если так пишется, компилятор понимает, что объект типа derived также является объектом типа base, но объект типа base не является объектом типа derived. Это очень важно. Тогда функция с параметром типа base подходит для derived, а функция с параметром типа derived не подходит для base. Вот пример кода, функция с параметром base,传入 derived должна успешно выполнить, напротив, функция с параметром derived

#include <iostream>
#include <stdio.h>
class base
{
  public:
  base()
  :baseName(""),baseData(0)
  {}
  base(std::string bn,int bd)
  :baseName(bn),baseData(bd)
  {}
  std::string getBaseName() const
  {
    return baseName;
  }
  int getBaseData()const
  {
    return baseData;
  }
  private:
    std::string baseName;
    int baseData;
};
class derived:public base
{
  public:
    derived():base(),derivedName("")
    {}
    derived(std::string bn,int bd,std::string dn)
    :base(bn,bd),derivedName(dn)
    {}
    std::string getDerivedName() const
    {
      return derivedName;
    }
  private:
    std::string derivedName;
};
void show(std::string& info,const base& b)
{
  info.append("Name is ");
  info.append(b.getBaseName());
  info.append(", baseData is ");
  char buffer[10];
  sprintf(buffer,"%d",b.getBaseData());
    info.append(buffer);
}
int main(int argc, char* argv[])
{
  base b("test",10);
  std::string s;
  show(s,b);
  std::cout<<s<<std::endl;
  derived d("btest",5,"dtest");
  std::string ss;
  show(ss,d);
  std::cout<<ss<<std::endl;
  return 0;
}

Результат выполнения:

base: baseName is test, baseData is 10
base: baseName is btest, baseData is 5

Измените код, чтобы параметр функции стал derived

void show2(std::string& info,const derived& d)
{
  info.append("Name is ");
  info.append(d.getBaseName());
  info.append(", baseData is ");
  char buffer[10];
  sprintf(buffer,"%d",d.getBaseData());
  info.append(buffer);
}

Вызов show(ss,d); компилятор выдает ошибку

1 derived_class.cpp: В функции `int main(int, char**)':
2 derived_class.cpp:84: ошибка: недопустимое инициализирование ссылки типа 'const derived&' из выражения типа 'base'
3 derived_class.cpp:70: ошибка: при передаче аргумента 2 функции `void show2(std::string&, const derived&)'

Второй пункт проверяет различные формы наследования, сначала давая таблицу

Способ наследования \ тип члена public protected private
public public protected Невозможно наследовать
protected protected protected Невозможно наследовать
private private private Невозможно наследовать

Вот объяснение: здесь просто выражается член базового класса, который после наследования public, protected, private в базовом классе в классе наследования имеет тип, указанный в таблице

class base
{
  public:
    std::string testPublic()
    {
      return std::string("this is public base");
    }
  protected:
    std::string testProtected()
    {
      return std::string("this is protected base");
    }
  private:
    std::string testPrivate()
    {
      return std::string("this is private base");
    }
};
class derivedPublic:public base
{
  public:
    std::string testPubPublic()
    {
      return testPublic() += "in derived";
    }
    std::string testProPublic()
    {  
      return testProtected() += "in derived";
    }
    std::string testPriPublic()          
    {  
      return testPrivate() += "in derived";
    }
};
int main(int argc, char* argv[])
{
  derivedPublic dpub;
  std::cout << dpub.testPublic() << std::endl; 
}

Отчет о следующей ошибке означает, что testPrivate() не является частной функцией derived, а является частной функцией base

derived11.cpp:16: ошибка: `std::string base::testPrivate()' является частной
derived11.cpp:36: ошибка: в данном контексте

Таким образом, проверяется, что частные типы членов не могут быть наследованы (public, private, protected). Примечание: private, protected пропущены для доказательства.

Ниже только проверяется, что testProtected может быть наследован классом третьего уровня, но не может быть вызван напрямую классом третьего уровня, что означает, что тип наследования после public наследования является protected, а если члены базового класса являются public, protected, private, то они могут быть наследованы и напрямую вызываться.

#include <iostream>
#include <string>
class base
{
  public:
    std::string testPublic()
    {
      return std::string("this is public base");
    }
  protected:
    std::string testProtected()
    {
      return std::string("this is protected base");
    }
  private:
    std::string testPrivate()
    {
      return std::string("this is private base");
    }
};
class derivedPublic:public base
{
  public:
    std::string testPubPublic()
    {
      return testPublic() += "in derived";
    }
    std::string testProPublic()
    {  
      return testProtected() += "in derived";
    }
//    std::string testPriPublic()          
//    {  
//      return testPrivate() += "in derived";
//    }
};
class deepDerived:public derivedPublic
{
  public:
    std::string deepProtected()
    {
      return testProtected() += "in deep";
    }
    std::string deepPublic()
    {
      return testPublic() += "indeep";
    }
};
int main(int argc, char* argv[])
{
  derivedPublic dpub;
  std::cout << dpub.testProtected() << std::endl; 
  deepDerived deepdpub;
  std::cout << deepdpub.testPublic() << std::endl;
  std::cout << deepdpub.testProtected() << std::endl;
  std::cout << deepdpub.deepProtected() << std::endl;
  std::cout << deepdpub.deepPublic() << std::endl;
}

Здесь сервер сообщает об ошибке

derived12.cpp:13: ошибка: `std::string base::testProtected()` является защищенным
derived12.cpp:62: ошибка: в данном контексте

Таким образом, был проверен один public и один protected. Protected не может быть вызван напрямую, но может быть вызван через public член, наследованный.
Ниже уже доказано, подробные шаги опущены. Если вы заинтересованы в этой части проверки, см. следующий код.

#include <iostream>
#include <string>
class base
{
  public:
    std::string testPublic()
    {
      return std::string("this is public base");
    }
  protected:
    std::string testProtected()
    {
      return std::string("this is protected base");
    }
  private:
    std::string testPrivate()
    {
      return std::string("this is private base");
    }
};
class derivedPublic:public base
{
  public:
    std::string testPubPublic()
    {
      return testPublic() += "in derived";
    }
    std::string testProPublic()
    {  
      return testProtected() += "in derived";
    }
//    std::string testPriPublic()          //私有成员并没有被继承下来
//    {  
//      return testPrivate() += "in derived";
//    }
};
class deepDerived:public derivedPublic
{
  public:
    std::string test()
    {
      return testPublic() +="in 3";
    }
};
class derivedProtected:protected base
{
  public:
    std::string testPubProtected()
    {
      return testPublic() += "in derived";
    }
    std::string testProProtected()
    {  
      return testProtected() += "in derived";
    }
};
class deepDerived2:public derivedProtected
{
  public:
    std::string test()
    {
      return testPublic() +="in 3";
    }
};
class derivedPrivate:private base
{
  public:
    std::string testPubPirvate()
    {
      return testPublic() += "in derived";
    }
    std::string testProPrivate()
    {  
      return testProtected() += "in derived";
    }
};
//class deepDerived3:public derivedPrivate
//{
//  public:
//    std::string test()
//    {
//      return testPublic() += "in 3";
//    }
//};
int main(int argc, char* argv[])
{
  derivedPublic dpub;
  //derivedProtected dpro;
  //derivedPrivate dpri;
  std::cout << dpub.testPublic() << std::endl;
  //std::cout << dpub.testProtected() << std::endl;  //Пользователи, наследующиеся, также не могут использовать
  //cout << dpub.testPrivate() << std::endl;     //Базовые классы имеют私有ные функции
  std::cout << dpub.testPubPublic() << std::endl;
  std::cout << dpub.testProPublic() << std::endl;
  //std::cout<<dpub.testPriPrivate()<<std::endl; // not inherited
  deepDerived dd;
  std::cout<<dd.test()<<std::endl;
  derivedProtected dpro;
  //std::cout<<dpro.testPublic()<<std::endl;    // turned into protected type
  std::cout<<dpro.testPubProtected()<<std::endl;
  std::cout<<dpro.testProProtected()<<std::endl;
  deepDerived2 dd2;
  std::cout<<dd2.test()<<std::endl;
  derivedPrivate dpri;
  std::cout<<dpri.testPubPirvate()<<std::endl;
  std::cout<<dpri.testProPrivate()<<std::endl;
//  deepDerived3 dd3;
//  std::cout<<dd3.test()<<std::endl;
}

Это является материалом для систематизации C++ j наследования, продолжат дополнять соответствующие материалы, спасибо всем за поддержку нашего сайта!

Заявление: данное содержимое взято из Интернета, авторские права принадлежат соответствующему автору, содержимое предоставлено пользователями Интернета в добровольном порядке, сайт не обладает правами собственности, не underwent редактирование, не несет ответственности за соответствующие юридические вопросы. Если вы обнаружите содержимое,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (во время отправки письма, пожалуйста, замените # на @) для сообщения о нарушении,并提供 соответствующие доказательства. Если подтвердится, сайт немедленно удалил涉嫌侵权的内容。

Рекомендуем также