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;
}
目录
相关文章
|
14天前
|
编译器 C++
【C++】详解C++的继承
【C++】详解C++的继承
|
2月前
|
C++
C++中的封装、继承与多态:深入理解与应用
C++中的封装、继承与多态:深入理解与应用
47 1
|
1月前
|
编译器 数据安全/隐私保护 C++
c++primer plus 6 读书笔记 第十三章 类继承
c++primer plus 6 读书笔记 第十三章 类继承
|
4天前
|
存储 Java 程序员
【c++】继承深度解剖
【c++】继承深度解剖
8 1
|
12天前
|
存储 编译器 数据安全/隐私保护
|
19天前
|
C++
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
20 0
C++职工管理系统(类继承、文件、指针操作、中文乱码解决)
|
19天前
|
C++
【C++】学习笔记——继承_2
【C++】学习笔记——继承_2
19 1
|
21天前
|
编译器 C++
C++中的继承
C++中的继承
20 1
|
24天前
|
C++
C++一分钟之-继承与多态概念
【6月更文挑战第21天】**C++的继承与多态概述:** - 继承允许类从基类复用代码,增强代码结构和重用性。 - 多态通过虚函数实现,使不同类对象能以同一类型处理。 - 关键点包括访问权限、构造/析构、菱形问题、虚函数与动态绑定。 - 示例代码展示如何创建派生类和调用虚函数。 - 注意构造函数初始化、空指针检查和避免切片问题。 - 应用这些概念能提升程序设计和维护效率。
22 2
|
26天前
|
C++
C++:继承性
C++:继承性
22 2