8. C++继承

简介: 8. C++继承

C++继承

继承遗传学中继承概念,继承的写法,以及继承中的权限问题,继承中的构造函数写法

继承的实质就是父类有的属性在子类中也存在一份。只是根据继承方式不同,在子类中权限的体现不同。

继承:子类没有新的属性或者行为产生

  • 父类
  • 子类

派生:派生类中有新的属性产生

  • 基类
  • 派生类

单继承

只有父类的继承称之为单继承

写法

class 父类
{
    
};
class 子类:继承方式 父类名
{
};
//继承方式就是权限限定词
//公有继承: public
//保护继承: protected
//私有继承: private

继承中权限问题

public

protected

private

public继承

public

protected

不可访问

protected继承

protected

protected

不可访问

private继承

private

private

不可访问

综上: 权限限定词只会增强权限(public:最低权限  private:最高权限)

#include <iostream>
#include <string>
using namespace std;
//父类
class MM 
{
public:
  string getName() { return name; }
  void print() 
  {
    cout << name << "\t" << age << endl;
  }
protected:
  int age=18;
private:
  string name="默认";
};
//子类
//公有继承
class Boy :public MM 
{
public:
  //print()
  void printBoy() 
  {
    //cout << name << endl;  不可能访问
    cout << age << endl;
    print();
  }
protected:
  //int age
private:
  //string name; 不能访问
};
//保护继承
class Girl :protected MM 
{
public:
  void printGirl() 
  {
    cout << age << endl;
    print();
  }
protected:
  //void print()
  //int age;
private:
  //string name;
};
//私有继承
class Son :private MM
{
public:
  void printSon()
  {
    print();
    cout << age << endl;
    //cout << name << endl;       //父类的私有属性子类不能使用
    //只能间接调用父类的非私有方法访问
    cout << getName() << endl;
  }
protected:
private:
  //void print();
  //int age;
  //string name;
};
int main() 
{
  Boy boy;
  boy.print();
  boy.printBoy();
  Girl girl;
  //girl.print(); //无法访问
  girl.printGirl();
  Son son;
  son.printSon();
  return 0;
}

注意点:

  • 继承的属性无论被继承多少次,都存在, A 被B继承 B被C继承 C被D继承 D包含ABC中所有属性
  • 继承不易过多继承,导致子类臃肿
  • 私有继承可以阻断父类属性被孙子类去使用(断子绝孙)

继承中构造函数写法

  • 写法:子类必须先构造父类对象(子类必须调用父类的构造函数) ,调用父类的构造函数必须采用初始化参数列表
  • 构造和析构顺序问题
#include <iostream>
#include <string>
using namespace std;
class A 
{
public:
  A() 
  {
    cout << a;
  }
  A(string a):a(a)
  {
    cout << a;
  }
  ~A() 
  {
    cout << a;
  }
protected:
  string a="A";
};
class B :public A
{
public:
  B()         //就算没写,也会调用父类的无参构造函数    
  {
    cout << b;
  }
  //子类完整写法: 除了初始化自身数据,还需要初始化父类数据
  B(string a, string b) :A(a)
  {
    this->b = b;  //自身属性可以采用初始化列表
    cout << b;
  }
  void print() 
  {
    cout << a;
    cout << b;
  }
  ~B() 
  {
    cout << b;
  }
protected:
  string b = "B";
};
class C :public B 
{
public:
  C(string a, string b, string c) :B(a, b), c(c) 
  {
    cout << c;
  }
  void print() 
  {
    cout << a << b << c << endl;
  }
  ~C() 
  {
    cout << c;
  }
protected:
  string c;
};
int main() 
{
  {
    B b;
    cout << endl;
    B object("A", "B");
    cout << endl;
    object.print();
    cout << endl;
    C c("A","B","C");
    cout << endl;
    c.print();
  }
  cout << endl;
  {
    cout << "构造和析构顺序问题:" << endl;
    C cobject("A", "B", "C");
    //ABCCBA
  }
  return 0;
}

多继承

多继承就是存在两个以及两个以上父类

  • 权限问题和构造函数和单继承一样的
#include <iostream>
#include <string>
using namespace std;
class Father 
{
public:
  Father(string FFName) :FFName(FFName) {}
protected:
  string FFName;
};
class Monther 
{
public:
  Monther(string MFName) :MFName(MFName) {}
protected:
  string MFName;
};
class Son :public Father, public Monther 
{
public:
  Son(string FFName, string MFName, string SSName) :Father(FFName),Monther(MFName)
  {
    this->SFName = FFName + MFName;
    this->SSName = SSName;
  }
  void print() 
  {
    cout << FFName << endl;
    cout << MFName << endl;
    cout << this->SFName + this->SSName << endl;
  }
protected:
  string SFName;
  string SSName;
};
int main() 
{
  Son son("李","田","大牛");
  son.print();
  return 0;
}

菱形继承

菱形继承是因为多继承存在问题而衍生的继承方式(菱形继承就是虚继承)

(题目可能会出现,但是自己写代码不会出现)

#include <iostream>
#include <string>
using namespace std;
class A 
{
public:
  A(int a) :a(a) {}
  int a=666;
};
class B :virtual public A
{
public:
  B(int a) :A(a) {}
};
class C :virtual public A
{
public:
  C(int a) :A(a) {}
};
class D :public C, public B      //多继承构造顺序只和这个地方顺序(继承顺序)有关
{
public:
  D(int a) : C(14), B(12) ,A(a)     //子类必须调用爷爷构造函数
  {
  }
  void print() 
  {
    cout << A::a << endl; 
    cout << B::a << endl; 
    cout << C::a << endl; 
  }
};
int main() 
{
  D dobject(23);
  dobject.print();
  return 0;
}

继承中同名问题

  • 数据成员同名
  • 成员函数同名
#include <iostream>
#include <string>
using namespace std;
class MM 
{
public:
  MM(string name) :name(name) {}
  void print() 
  {
    cout << "-------------------------" << endl;
    cout << "MM::name" << endl;
    cout << "-------------------------" << endl;
  }
protected:
  string name;
};
class Son :public MM 
{
public:
  Son() :name("Son"), MM("MM")
  {
  }
  void print() 
  {
    cout << "-------------------------" << endl;
    cout << "Son::name" << endl;
    //No.1 不写任何标识 ,就近原则
    cout << name << endl;
    //No.2 可以用类名
    cout << MM::name << endl;
    cout << "-------------------------" << endl;
  }
protected:
  string name;
};
void printInfo(MM* p) 
{
  p->print();
}
int main() 
{
  //对象访问:
  //No.1 不写任何标识 ,就近原则
  Son son;
  son.print();
  son.MM::print();
  son.Son::print();
  MM mm("MM");
  mm.print();
  //指针访问
  //正常初始化访问
  cout << "正常初始化指针访问" << endl;
  Son* pSon = new Son;
  pSon->print();
  MM* pMM = new MM("MM");
  pMM->print();
  //非正常初始化访问
  //1.1 父类指针用子类对象初始化
  //在没有写任何修饰词的,看指针类型
  MM* pFather = new Son;
  pFather->print();       //调用那个函数?
  //1.2 子类指针被父类对象初始化,危险,一般不这样做
  //Son* pp = new MM("MM");   //错误的
  Son* pp = NULL;
  pp = static_cast<Son*>(&mm);  //强制类型转换类似C语言强制
  //pp->print();          //程序中断,没办法执行
  cout << "当父类指针成为函数参数时候,传参子类和父类对象通用" << endl;
  printInfo(pMM);
  printInfo(pSon);
  return 0;
}
目录
相关文章
|
4月前
|
编译器 C++
【C++】详解C++的继承
【C++】详解C++的继承
|
1月前
|
安全 程序员 编译器
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
【C++篇】继承之韵:解构编程奥义,领略面向对象的至高法则
77 11
|
1月前
|
C++
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
C++番外篇——对于继承中子类与父类对象同时定义其析构顺序的探究
51 1
|
1月前
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
39 1
|
27天前
|
安全 编译器 程序员
C++的忠实粉丝-继承的热情(1)
C++的忠实粉丝-继承的热情(1)
15 0
|
1月前
|
编译器 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
C++入门11——详解C++继承(菱形继承与虚拟继承)-2
27 0
|
1月前
|
程序员 C++
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
C++入门11——详解C++继承(菱形继承与虚拟继承)-1
31 0
|
2月前
|
C++
C++(二十)继承
本文介绍了C++中的继承特性,包括公有、保护和私有继承,并解释了虚继承的作用。通过示例展示了派生类如何从基类继承属性和方法,并保持自身的独特性。此外,还详细说明了派生类构造函数的语法格式及构造顺序,提供了具体的代码示例帮助理解。
|
2月前
|
C++
c++继承层次结构实践
这篇文章通过多个示例代码,讲解了C++中继承层次结构的实践应用,包括多态、抽象类引用、基类调用派生类函数,以及基类指针引用派生类对象的情况,并提供了相关的参考链接。
|
3月前
|
安全 Java 编译器