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中也存在多态的使用,比如函数重载,今天我们先看一下函数重载以及泛型的概念. 什么是函数重载 简单来说,函 ...
随机推荐
- mysql 表锁——读锁和写锁
注意, 0.表的索引类型必须是InnoDB.相关链接:http://www.cnblogs.com/CyLee/p/5579672.html 1.如果你使用Navicat Premium,有可能会出现 ...
- Latex--TikZ和PGF--高级文本绘图,思维绘图,想到--得到!
Latex--TikZ和PGF--高级文本绘图,思维绘图,想到--得到! TikZ和PGF是一种用在TeX上的CLI绘图工具.CLI和GUI是两种常见的绘图方式,前者是所想即所得(WYTIWYG)的, ...
- eclipse部署class默认在build文件夹
1.eclipse新建的Dynamic web project 默认是将类编译在build如果在eclipse中配置了tomcate(server项),用自带的发布功能,是能自动识别的.2.自已修改到 ...
- java线程高并发编程
java线程具体解释及高并发编程庖丁解牛 线程概述: 祖宗: 说起java高并发编程,就不得不提起一位老先生Doug Lea,这位老先生可不得了.看看百度百科对他的评价,一点也不为过: 假设IT的历史 ...
- 利用Java剖析工具JProfiler查找内存泄漏的方法
本文主要介绍如何如何利用在使用JProfiler时意识到内存泄漏以及查找内存泄漏的几种方法. 工具/原料 JProfiler 方法/步骤 JProfiler的内存视图会话提供了内存使用情况的动 ...
- ny27 水池数目
水池数目 时间限制:3000 ms | 内存限制:65535 KB 难度:4 描述 南阳理工学院校园里有一些小河和一些湖泊,现在,我们把它们通一看成水池,假设有一张我们学校的某处的地图,这个地图上 ...
- hdoj2037 今年暑假不AC
今年暑假不AC Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- 三、为什么String在Java中是不可更改的
String在Java中是个不可更改的类.一个不可更改的类简单来说就是这个类的所有实例是不可以更改的.所有的实例信息在创建的时候被初始化而且信息是不可以更改的.不可更改的类有很多好处.这篇文章总结了为 ...
- Qt入门-layout布局
开发一个图形界面应用程序,界面的布局影响到界面的美观.在设计一个界面之前,应该考虑到开发的界面可能给不用的用户使用,而用户的屏幕大小.纵横比例.分辨率可能不同,界面还可能是可缩放的,程序应该可以适应这 ...
- 利用对象思想来绘制canvas帧动画
绘制思路: 1.封装一个对象出来: 2.属性: width . height imgSr speed dir3.行为: render changeDir html文件: <script> ...