C++ 继承、函数重载
题外话1:浪费了两天,可耻!
题外话2:你这个年纪,做得好是理所当然,做不好是罪孽深重!!! --- 深以为然。
题外话3:从开始看C++ Primer 到现在,整整24天了,没想到基础方面耗费这么久---主要是没想到C++居然如此繁琐。精勤求学,当持之以恒。
面向对象的三大特征:数据抽象、继承、动态绑定。其实就是Java中说的封装、继承、多态,翻译的不同而已。
多态这个词用的不好,太抽象,动态绑定就清晰的多。
继承语法
class B : public A { /*类B*/ };
上面最重要的就是“:”和public。前者记住就行,继承的语法规定。后者是权限访问符(我更喜欢叫它继承权限),public、protected、private。
继承权限和父类成员的访问权限,共同决定了继承的成员在子类中的访问权限---继承权限可以进一步限制,但不能放松---最小访问控制。
例如父类的public成员a,继承权限为private,则a在子类中就是private部分。
这里只有一个需要注意的点,如果省略继承权限,那么 class 默认为private,struct默认为public。
补充:
//using声明导入
class Derived : private Base {
public:
// maintain access levels for members related to the size of the object
using Base::size;
protected:
using Base::n;
// ...
};
继承的结构
子类对象的父类部分其实就是一个父类对象!这个认识很重要!
父类的引用或者指针,指向的就是子类对象的父类对象部分!!!
动态绑定
首先,这是一个运行期的概念,它出现的条件是:通过父类的引用或指针调用函数。
这点同Java的概念一样。但有一点不同:动态绑定仅限于 virtual 函数!
就是说,普通的函数不会动态绑定!!!这个认识更重要!
普通函数的绑定是编译器进行的,静态绑定。
这里的关键点是,父类的引用或者指针是静态类型,而子类对象(或者父类本身的对象)是在运行期才知道的。所以叫动态绑定。
就是说,对象的实际类型可能不同于父类的引用或指针类型,这是C++动态绑定的关键。
关于虚函数
不是重载,是重写。
如果想调用某个父类的虚函数,需要使用作用域操作符,如 A::x(); --仅限于子类的成员函数中调用。
注意:虚函数的默认实参如果不一致,会导致问题。
继承之初始化
隐式的,会调用父类的默认构造进行初始化。再初始化子类自身的成员。
显式的,只能在子类的初始化列表中调用父类的构造进行初始化。
--- 注意,都是先初始化父类对象,且只能直接初始化直接父类。
继承之复制控制
隐式的,会调用父类的复制控制操作父类成员。再调用子类的复制控制。
如果自定义了复制构造函数,应该显式的调用父类的复制构造函数操作父类成员。
如果自定义了赋值操作符,应该显式的调用父类的赋值操作符操作父类成员。
--- 注意,必须防止赋值操作符操作自身!
B &B::operator=(const B &rhs){
if(this != &rhs){
A::operator=(rhs); // 显式调用父类的赋值操作符
/*其他*/
}
}
继承之析构函数
注意,子类析构不负责父类析构,而是由编译器显式的调用父类的析构函数!
需要将根类的析构函数设为虚函数!!
析构顺序与构造顺序相反。
纯虚函数
在虚函数的参数列表后面加上 =0 ,即将该虚函数声明为纯虚函数。
具有该函数的类将无法创建对象。
--这个就和Java的抽象方法、抽象类一致了。
重要
在构造或者析构期间,总是先构造父类或者析构子类,这时类型是不完整的。
为了解决这个问题,编译器将构造或者析构期间的对象看作父类对象!!!
所以,构造或者析构期间调用的虚函数只会是构造或者析构函数所在类的虚函数!不是子类的虚函数!!!
函数重载
子类的同名函数会覆盖掉父类中所有的同名函数--哪怕是不同的函数原型!!!(务必注意,非 virtual)
认真的说,我不认为这是重载,不过书上这么叫,那就这么叫吧。
这种覆盖用起来很不爽,因为完全覆盖了所有的父类版本。所幸我们有比较好的解决办法:使用using声明。
#include <iostream> using namespace std; // 根类的析构函数,必须virtual。
// 子类的函数会覆盖父类的同名函数。
// 如果想重载,使用using声明即可。
class A
{
public:
A(){};
virtual ~A(){};
void hi(){
cout<<"hi from A"<<endl;
}
void hi(string name){
cout<<"hi "<<name<<" from A"<<endl;
}
}; class B:public A
{
public:
B(){};
~B(){};
using A::hi; // using 声明
void hi(int num){
cout<<"hi num["<<num<<"] from B, overloaded"<<endl;
} }; int main(int argc, char const *argv[])
{
B b;
b.hi();
b.hi("joe");
b.hi(); return ;
}
继承特性:
友元关系不能继承。
静态成员只会存在一个实例。
构造函数和复制控制不能继承。
根类的析构函数应该设为虚函数。
构造函数和析构函数都只能调用所在类的函数,哪怕是虚函数---就是说构造或者析构期间没有动态绑定。
C++ 继承、函数重载的更多相关文章
- C++ 函数重载与函数匹配
<C++ Primer>笔记,整理关于函数重载与函数匹配的笔记. 函数重载 void func(int a); //原函数 void func(double a); //正确:形参类型不同 ...
- php继承与重载
<?php class A { public $param = "paramA"; public function test() { echo "testA&quo ...
- php 之 类,对象(三)多态性,函数重载,克隆
一.三大特性之三 多态性(在php中表象不明显)1.概念:当父类引用指向子类实例时,由于子类对父类函数进行了重写,导致我们在使用该引用去调用相应的方法显示出的不同.2.发生条件:1.必须有继承 2. ...
- 5.3 C++用顶层函数重载操作符
参考:http://www.weixueyuan.net/view/6381.html 总结: 可以将操作符重载函数声明为顶层函数. 如果以顶层函数的形式重载操作符时,二元操作符重载函数必须有两个参数 ...
- python中函数重载和重写
python 中的重载 在python中,具有重载的思想却没有重载的概念.所以有的人说python这么语言并不支持函数重载,有的人说python具有重载功能.实际上python编程中具有重载的目的缺 ...
- 函数重载(overload)和函数重写(override)
1. 前言: 在C++中有两个非常容易混淆的概念,分别是函数重载(overload)和函数重写(overwirte).虽然只相差一个字,但是它们两者之间的差别还是非常巨大的. 而通过深入了解这两个概念 ...
- 0607pm克隆&引用类&加载类&面向对象串讲&函数重载
克隆class Ren{ public $name; public $sex; function __construct($n,$s) { $this->name=$n; $this->s ...
- C++学习_继承覆盖重载
今天通过对实验二继承,重载,覆盖的学习,让我更深一步理解了这些概念的区别. 首先来明确一个概念,函数名即地址,也就是说函数名就是个指针. 编译阶段,编译器为每个函数的代码分配一个地址空间并编译函数代码 ...
- 深入浅出TypeScript(3)- 函数重载和泛型
面向对象特性中,最根本的就是面向对象的三大基本特征:封装.继承.多态.同时,TypeScript中也存在多态的使用,比如函数重载,今天我们先看一下函数重载以及泛型的概念. 什么是函数重载 简单来说,函 ...
随机推荐
- jenkins构建自动执行jmeter 发送http请求,中间有替换参数路径
#在构建目录下创建jmeter目录,在这个目录下面执行jmeter性能测试mkdir -p $WORKSPACE/target/apache-jmeter-3.1/#复制jmeter文件到执行测试目录 ...
- mysql-5.7 扩展innodb系统表空间详解
一.innodb系统表空间的简介: innodb 系统表空间是由若干个文件组成的,表空间的大小就是对应文件的大小,表空间文件是由innodb_data_file_path 这人参数来定义的.下面我们来 ...
- 进程间通信(java)--队列
前言: 在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题.通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便 ...
- angular.js快速入门 hello world
我们整个系列的学习会去写一个简单blog雏形,如果有精力再完善美化. 但是这篇还是要从HelloWorld开始学习. angular.js 文件加载我们选用 bootstrap中文网提供的一个cdn服 ...
- extjs中组件监听器里面的回调函数说明
近期在看项目源代码的时候发现了例如以下代码,当中_searchSupplierStore是JsonStore对象 _searchSupplierStore.on('beforeload',functi ...
- Python并发编程实例教程
有关Python中的并发编程实例,主要是对Threading模块的应用,文中自定义了一个Threading类库. 一.简介 我们将一个正在运行的程序称为进程.每个进程都有它自己的系统状态,包含内存状态 ...
- Python标准库:内置函数getattr(object, name[, default])
本函数实现获取对象object的属性.属性由name来表示,就是属性名称的字符串.參数default是可选的參数,当获取对象的属性不存在时,就返回此值.假设没有提供此參数.同一时候在对象属性里也找不到 ...
- Linux系统_Linux平台“盖茨木马”初步了解
静态分析: # file Yang Yang: ELF -bit LSB executable, Intel , version (SYSV), statically linked, , not st ...
- C++ 顺序容器原理
容器分为顺序容器与关联容器,顺序容器也称为序列式容器.序列式容器按元素插入的顺序存储元素,这些元素可以进行排序,但未必是有序的.C++本身内置了一个序列式容器array(数组),STL另外提供了vec ...
- python定制类详解
1.什么是定制类python中包含很多内置的(Built-in)函数,异常,对象.分别有不同的作用,我们可以重写这些功能. 2.__str__输出对象 class Language(object): ...