继承是面向对象复用的重要手段。通过继承定义一个类,继承是类型之间的关系建模,共享共有的东西,实现各自本质不同的东西。

成员访问限定符&继承关系:

这是一个简单的继承关系:

#include<iostream>
#include<Windows.h>
using namespace std;
class person
{
public:char* name;char* sex;int age;
public:void display(){cout << "name:" << name << "  sex:" << sex << "  age:" << age << endl;}
};
class student :public person
{
public:int stdnum;
public:void show(){cout << "stdnum:" << stdnum << endl;}
};
int main()
{student s;s.name = "xiaowang";s.sex = "man";s.age = 18;s.stdnum = 2016;s.display();s.show();system("pause");return 0;
}

代码执行时的情况:

继承是一种复用手段,在继承关系基类的成员类的成员派生类的成员,从而达到复用多个目的。

三种继承关系下基类成员在派生类的访问关系变化:

总结:

  • 基类的私有成员在派生类中是不能被访问的,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
  • public继承是一个接口继承,保持is-a原则,每个父类可用的成员对子类也可用,因为每个子类对象都是一个父类对象。
  • protected继承/private继承是一个实现继承,基类的部分成员并非完全成为子类接口的一部分,是has-s的原则,所以大多数情况下不使用这两种继承,绝大多数场景都是公有继承。
  • 不管哪种继承方式,在派生类内部都可以访问基类的公有成员和保护成员,基类的私有成员存在但是在子类中不可见,即不能访问。
  • 使用关键字class默认继承方式是private使用struct时默认的继承方式是public,最好显示出继承方式。

赋值兼容规则–public继承

  1. 子类对象可以赋值给父类对象(切割/切片)
  2. 父类对象不能赋值给子类对象
  3. 父类的指针/引用 可以指向子类对象
  4. 子类的指针/引用不能指向父类对象(可以通过强制类型转换完成,但不能调用成员函数,会崩溃)
class person
{
public:char* name;char* sex;int age;
public:void display(){cout << "name:" << name << "  sex:" << sex << "  age:" << age << endl;}
};
class student :public person
{
public:int stdnum;//学号
public:void show(){cout << "stdnum:" << stdnum << endl;}
};
int main()
{person p;p.name = "xiaozhang";p.age = 18;student s;s.name = "xiaowang";p.age = 20;// 切割/切片// 子类可以给父类赋值p = s;  //父类不能给给子类赋值//s=p;//父类的指针可以指向子类对象person* p1 = &s;//父类的引用可以指向子类对象person& r1 = s; p1->name = "xx";r1.name = "yy";//子类的指针/引用不能指向父类(可以通过强制类型转换完成)student* p2 = (student*)&p;student& r2 = (student&)p;p2->name = "xx";r2.name = "yy";system("pause");return 0;
}

派生类的默认成员函数

在继承关系里面,在派生类中如果没有显示定义的这六个成员函数,编译系统则会默认合成这六个默认的成员函数

1.构造函数
子类的构造函数会自动调用父类的构造函数。
派生类构造函数必须使用基类构造函数。
构造函数不同于其他类的方法,应为它创建新的对象,要调用基类中的私有成员,因为派生类不能直接访问基类的私有成员,必须要调用基类方法进行访问,而其他类仅仅是被现有的对象调用而已,所以构造函数不能被继承;
基类的构造函数先被调用,后面是派生类的构造函数,其实,在main函数中,先调用的是派生类的构造函数,基类的构造函数是在派生类的初始化列表中调用

class Person
{
public:Person(const char* name = "", int age = 0):_name(name), _age(age){cout << "Person()" << endl;}
}
class Student : public Person
{
public:Student(const char* name, int age, int stunum):Person(name, age){_stunum = stunum;cout << "Student()" << endl;}
}

2.拷贝构造函数
子类的拷贝构造函数会自动调用父类的拷贝构造函数。
拷贝构造会有切片。
在下列情况下使用拷贝构造:

  1. 将新的对象初始化为一个同类对象
  2. 按值将对象传递给函数
  3. 函数按值返回对象
  4. 编译器生成临时对象

如果程序没有显式定义拷贝构造函数,编译器将自动生成一个。
当然,如果想在派生类中构造基类对象,那么不仅仅可以用构造函数,也可以用拷贝构造函数

class Person
{
public:Person(const Person& p):_name(p._name), _age(p._age){cout << "Person(const Person& p)" << endl;}
}
class Student : public Person
{
public:Student(const Student& s):Person(s){_stunum = s._stunum;}
}

3.析构函数
子类析构函数与父类析构函数会构成隐藏(虽然名字不同,但编译器会使他们重名,从而构成隐藏)
为了保证析构顺序,系统会自己调用析构函数,依据栈的规则,先call子类析构,在call父类析构
初始化时,父类先初始化,子类后初始化
析构时,子类先析构,父类后析构。栈的后进先出

class Person
{
public:~Person(){cout << "~Person()" << endl;}
}
class Student : public Person
{
public:~Student() //隐藏了父类的析构函数{Person::~Person();cout << "~Student()" << endl;}
}

4.赋值操作符重载
子类对象可以赋值给父类对象
子类的赋值操作符重载会自动调用父类的赋值操作符重载。
赋值运算符是不能被继承的,原因很简单。派生类继承的方法的特征与基类完全相同,但赋值操作符的特征随类而异,因为它包含一个类型为其所属类的形参。
如果编译器发现程序将一个对象赋给同一个类的另一个对象,它将自动为这个类提供一个赋值操作符。这个操作符的默认版本将采用成员赋值,即将原对象的相应成员赋给目标对象的每个成员。
如果对象属于派生类,编译器将使用基类赋值操作符来处理派生对象中基类部分的赋值,如果显示的为基类提供了赋值操作符,将使用该操作符。

class Person
{
public:Person& operator=(const Person& p){if (this != &p){_name = p._name;_age = p._age;}return *this;}
}
class Student : public Person
{
public:Student& operator=(const Student& s){if (this != &s){Person::operator=(s);_stunum = s._stunum;}return *this;}
}

继承规则及派生类的成员函数相关推荐

  1. 类的成员函数指针(比较深入)

    From:http://blog.csdn.net/hairetz/archive/2009/05/06/4153252.aspx 个人感觉对于类的成员函数指针这块讲解的比较深入详细 推荐阅读 / 先 ...

  2. C++对象内存布局--③测试多继承中派生类的虚函数在哪一张虚函数表中

    C++对象内存布局--③测试多继承中派生类的虚函数在哪一张虚函数表中 测试2:证明派生类的虚函数的地址跟第一基类的虚函数地址保存在同一张虚函数表中. 派生类有多少个拥有虚函数的基类,派生类对象就有多少 ...

  3. 6-4 派生类使用基类的成员函数

    6-4 派生类使用基类的成员函数 分数 5 全屏浏览题目 切换布局 作者 李廷元 单位 中国民用航空飞行学院 按要求完成下面的程序: 1.定义一个Animal类,成员包括: (1)整数类型的私有数据成 ...

  4. C++模板学习02(类模板)(类模板语法、类模板与函数模板的区别、类模板中的成员函数创建时机、类模板对象做函数参数、类模板与继承、类模板成员函数类外实现、类模板分文件编写、类模板与友元)

    C++引用详情(引用的基本语法,注意事项,做函数的参数以及引用的本质,常量引用) 函数高级C++(函数的默认参数,函数的占位参数,函数重载的基本语法以及注意事项) C++类和对象-封装(属性和行为作为 ...

  5. 处理菱形继承问题实现一个虚函数的覆盖及调用实现以下几个类的成员函数...

    #include <iostream> #include <string> using namespace std; 1.实现以下几个类的成员函数 2.实现一个虚函数的覆盖及调 ...

  6. C++虚继承和虚基类;虚函数与继承

    ref http://blog.csdn.net/owen7500/article/details/52432970?locationNum=4&fps=1 http://blog.csdn. ...

  7. C++对象模型7——类的成员函数、反汇编虚析构函数、RTTI、多态的开销

    一.类成员函数 class test { public:void myfunc(){}virtual void vfunc() {}static void sfunc() {} };void myfu ...

  8. 类中成员函数声明后面的const的含义

    这个const一般是对类中成员函数属性的声明,但这个声明怪怪的,只能放在函数声明的尾部,大概是因为其它地方都已经被占用了.这个声明表示这个函数不会修改类中的任何数据成员.如果在编写const成员函数时 ...

  9. 类的成员函数与内联以及静态成员

    一.类的成员函数与内联 在类内定义的所有函数都自动称为内联函数.如果在类内声明,在类外定义,也可以定义为内联函数.在定义函数时添加inline限定符.. (1)此外,内联函数一定要和函数定义在一起,否 ...

最新文章

  1. 网络的塔建+模型训练
  2. JXJJOI2018_T2_tank
  3. Flink从入门到精通100篇(十九)-基于 Flink 的大规模准实时数据分析平台的建设实践
  4. 博客美化20150418
  5. ASP.NET Core HTTP 管道中的那些事儿
  6. android sonar 简书,SonarQube对ios、android代码检测
  7. 谈身份管理之基础篇 - 保障云上安全,从[规范账号使用]开始
  8. C语言程序设计第三节课作业
  9. 离散点自动生成等高线_有限自动机| 离散数学
  10. Hadoop配置项整理(hdfs-site.xml)
  11. 19) maven 项目结构:聚集
  12. linux终端黑绿字配色方案注意事项
  13. f分布表完整图a=0.01_QC七大手法(工具)完整版介绍
  14. 中标麒麟操作系统离线安装nginx
  15. 【QT】串口调试助手(串口编程代码详解)
  16. nRF51822 官方 Blinky 工程(多彩 LED)
  17. abs函数的使用方法 oracle,abs函数什么意思oracle
  18. arp欺骗盗取邻居wifi密码
  19. 地信实验一利用矢量化软件AutoCAD对栅格文件矢量化
  20. 科研绘图(编程绘图、网站绘图、配色、素材、提取数...)

热门文章

  1. C++计算球弹跳的高度
  2. kaniko kubernetes 构建镜像
  3. 【JavaScript】轻松入门
  4. 小米6Android8开发版,小米6安卓8.0系统来了 MIUI论坛开启内测招募
  5. Linux 各个发行版本的发展史
  6. 实现人工神经网络ANN对医疗数据分类
  7. 财富赢家模拟炒股最新版分享,股市小散的利器
  8. 现在JAVA工程师真是太卷了,招聘要求十条都算少的了
  9. 在线考试系统测试报告
  10. Delphi xe5如何使用Bluestacks模拟器。