(一)重载运算符:

(1)声明与定义格式
一般是类内声明,类外定义,虽然可以在类内定义,但 写前面堆一堆不好看!!!
类内声明

class Demo
{返回值类型 operator  运算符(形参表);
}

类外定义:

返回类型 Demo(类名)::operator运算符(形参表)
{函数体
}

(2)双目运算符重载为成员函数
当重载运算符为双目运算符时,形参表中只有一个参数作为右操作数。当前对象作为左操作数,通过this指针隐式传递给函数,一个例子来介绍。
实例:
写到最后突然想起来,用int不能实现浮点数的全部特性0.03就不能实现,所以仅作为一个例子。

class Myfloat
{int inter;int deci;
public:Myfloat(int a,int b):inter(a),deci(b){}Myfloat operator+(Myfloat const &temp) const;Myfloat operator-(Myfloat const &temp) const;
};
Myfloat Myfloat::operator+(Myfloat const &temp) const
{return Myfloat(inter+temp.inter,deci+temp.deci);
}
Myfloat Myfloat::operator-(Myfloat const &temp) const
{return Myfloat(inter-temp.inter,deci-temp.deci);
}

现在只是重载了加减号,实现了自定义浮点数的运算,但是还不成熟,咱们一点一点来丰满这个代码,这个类。(3)单目运算符重载为成员函数
此时参数表中没有参数,只有当前对象作为运算符的一个操作数。
实例:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
class Myfloat
{int inter;int deci;
public:Myfloat(int a,int b):inter(a),deci(b){}Myfloat operator+(Myfloat const &temp) const;Myfloat operator-(Myfloat const &temp) const;Myfloat operator--();Myfloat operator++();Myfloat operator--(int); //补充一个虚操作数,表示前置操作Myfloat operator++(int);
};
Myfloat Myfloat::operator+(Myfloat const &temp) const
{return Myfloat(inter+temp.inter,deci+temp.deci);
}
Myfloat Myfloat::operator-(Myfloat const &temp) const
{return Myfloat(inter-temp.inter,deci-temp.deci);
}
Myfloat Myfloat::operator--()  {return Myfloat(inter--,deci);}
Myfloat Myfloat::operator++()  {return Myfloat(inter++,deci);}
Myfloat Myfloat::operator--(int)  {return Myfloat(--inter,deci);}

要区分前置与后置运算要加一个(需操作数)告诉机器是前置还是后置。

(3) 友元函数重载+重载输入输出流(用的稀烂用的多比较重要)
在左右操作数类型不同时上述重载方式都不能正常使用,这时候就需要两个操作数,在类外重载,因类外不能直接调用,所以要把该函数声明为类的友元。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
class Myfloat
{int inter;int deci;
public:Myfloat(int a,int b):inter(a),deci(b){}Myfloat operator+(Myfloat const &temp) const;Myfloat operator-(Myfloat const &temp) const;Myfloat operator--();Myfloat operator++();Myfloat operator--(int); //补充一个虚操作数,表示前置操作Myfloat operator++(int);friend ostream& operator<<(ostream out,Myfloat &w) ;friend istream &operator>>(istream in,Myfloat &w);
};
Myfloat Myfloat::operator+(Myfloat const &temp) const{return Myfloat(inter+temp.inter,deci+temp.deci);}
Myfloat Myfloat::operator-(Myfloat const &temp) const{return Myfloat(inter-temp.inter,deci-temp.deci);}
Myfloat Myfloat::operator--()  {return Myfloat(inter--,deci);}
Myfloat Myfloat::operator++()  {return Myfloat(inter++,deci);}
Myfloat Myfloat::operator--(int)  {return Myfloat(--inter,deci);}
Myfloat Myfloat::operator++(int)  {return Myfloat(++inter,deci);}
ostream& operator<<(ostream out,Myfloat &w)
{out<<w.inter<<'.'<<w.deci;
}
istream &operator>>(istream in,Myfloat &w)
{in>>w.inter>>w.deci;
}

(4)赋值运算符重载用于对象数据的复制
用非类A类型的值为类A的对象赋值时(当然,这种情况下我们可以不提供相应的赋值运算符重载函数,而只提供相应的构造函数,如更有重载函数会优先调用重载后的赋值运算符)。
当用类A类型的值为类A的对象赋值,且类A的数据成员中含有指针的情况下,必须显式提供赋值运算符重载函数。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
class Myfloat
{int inter;int deci;
public:Myfloat(int a,int b):inter(a),deci(b){}Myfloat operator+(Myfloat const &temp) const;Myfloat operator-(Myfloat const &temp) const;Myfloat operator--();Myfloat operator++();Myfloat operator--(int); //补充一个虚操作数,表示前置操作Myfloat operator++(int);friend ostream& operator<<(ostream out,Myfloat &w) ;friend istream &operator>>(istream in,Myfloat &w);Myfloat& operator=(const Myfloat &temp ) ;//写或不写都可以,这种如果按照默认的方式一一对应复制,可以不写。Myfloat& operator=(const int &w ) ;
};
Myfloat Myfloat::operator+(Myfloat const &temp) const{return Myfloat(inter+temp.inter,deci+temp.deci);}
Myfloat Myfloat::operator-(Myfloat const &temp) const{return Myfloat(inter-temp.inter,deci-temp.deci);}
Myfloat Myfloat::operator--()  {return Myfloat(inter--,deci);}
Myfloat Myfloat::operator++()  {return Myfloat(inter++,deci);}
Myfloat Myfloat::operator--(int)  {return Myfloat(--inter,deci);}
Myfloat Myfloat::operator++(int)  {return Myfloat(++inter,deci);}
ostream& operator<<(ostream out,Myfloat &w)
{out<<w.inter<<'.'<<w.deci;
}
istream &operator>>(istream in,Myfloat &w)
{in>>w.inter>>w.deci;
}
Myfloat& Myfloat::operator=(const Myfloat &temp)
{inter=temp.inter;deci=temp.deci;return *this;
}
Myfloat& Myfloat::operator=(const int &w)
{inter=w;return *this;
}






(二)基类与派生类

(1)继承语法形式

class 派生类名:基类名表{数据成员和成员函数声明};

基类类名表构成: 访问控制 基类名1 访问控制 基类名2…
继承多各类时叫做多继承,容易产生二义性,一般不用。

访问控制有三种
public:公有继承
private:私有继承
protected:保护继承
实例

 class People { }class Student:public People


(2)派生类的生成过程

  1. 吸收基类成员:除构造和析构函数外
  2. 改造基类成员:通过在派生类中定义同名成员屏蔽基类成员在派生类中直接调用,仍可以基类指针调用同名成员
  3. .添加新成员

(3)派生类特点

  1. 子类拥有父类除了父类构造和析构函数,所有的成员函数和成员变量;
  2. 2.子类就是一种特殊的父类;
  3. 子类对象可以当做父类的对象使用;
  4. 子类可以拥有父类没有的方法和属性。

(4)派生类中的静态数据成员
基类中定义的静态成员,将被所有派生类共享
2、基类初始化:
(5)派生类的初始化

派生类构造函数声明格式为:
派生类构造函数(变元表):基类(变元表)、对象成员1(变元表)

构造函数执行顺序:基类——对象成员(类对象成员的初始化)——派生类
//一开始不理解,现在理解了
举个栗子:

class People
{protected:string  name;string  xb;
public:People(string a,string b):name(a),xb(b){}
};
class Cloth
{string color;int mysize;
public:Cloth(string c,int m):color(c),mysize(m){}
};
class Student:public People
{string id;Cloth coat;
public:Student(string id,string name,string xh,string color,int size) :People(name,xb),coat(color,size),id(id){}
};

执行顺序跟我写的顺序一样,但不是因为按这个顺序写的原因,就像成员变量初始化,也是按这定义顺序初始化,与自己写的初始化顺序无关。
构造函数的执行顺序:基类→对象成员→派生类;
(6)派生类构造函数和析构函数的使用原则

基类的构造函数和析构函数不能继承
派生类是否定义析构函数与所属基类无关
如果基类没有定义构造函数或是定义无参构造函数,派生类可以不定义构造函数。
如果基类无无参构造函数,派生类必须定义构造函数
如果派生类基类为连续基类继承,每个派生类只负责直接基类的构造

(7)派生类析构函数

与构造函数执行顺序相反,派生-----对象-----基类

(8)赋值兼容原则
这个规则可以简述为能放基类的地方,放派生类一定可以使用,在程序中需要使用基类对象的地方都可以用公有派生类的对象代替。
例:

class Base{};
class Drived{};
Base demo1,Drived demo2;
demo1=demo2;   //派生类对象可以赋值给基类对象:
Base&Bdemo3=demo2; //派生类对象可以初始化基类引用;
Base *Bpo=&demo2;//派生类对象可以赋给指向基类对象的指针;//多态实现的方法

主要是派生类中一定包含基类中所有成员,在使用中,一定可以找到对应成员。

赋值兼容应注意的问题:

  1. 指向基类的指针可以指向公有派生类的对象,但不允许指向它的私有派生类的对象。
  2. 允许将一个声明为指向基类的指针指向其公有派生类对象,但是不能将一个声明为指向派生类对象的指针指向基类对象。
  3. 声明为指向基类对象的指针,当其指向公有派生类对象时,只能用它来直接访问派生类中从基类继承来的成员,而不能直接访问公有派生类的定义的成员。

可以理解为派生类完全包含基类,指向基类的任何成员,都可以在公有派生类中找到对应的成员对象与之对应,如果是私有继承,能找到但是不能访问。但是派生类中有的对象,基类中不一定会有,所以不能这么操作。







(三)虚函数与多态:

(1)多态的概念:
一个接口,多种使用方法
(2)封装的作用:
封装可以是得代码模块化;继承可以扩展已经存在的代码,都是为了代代码重用;
**(3)多态的目的:**接口重用
(4)静态联编和动态联编分别表示什么?
在编译的时候能够确定对象所调用的成员函数的地址则为静态联编,一般的调用方式;
动态联编:指的是在程序运行的时候动态地进行,根据当时的情况来确定调用哪个同名函数,父类指针指向哪个子类,就调用哪个子类的同名函数,实际上是在运行的时候虚函数的实现;

#include<iostream>
using namespace std;class Basic
{public:void oper1(){printf("1\n");}virtual void oper2(){printf("2\n");}
};
class Direved : public Basic
{public:void oper1(){printf("3\n");}void oper2(){printf("4\n");}
};
int main(void)
{Basic a;Direved b;Basic *p = &a; //   定义一个基类指针    p->oper1();  //基类的oper1p->oper2();  //基类的oper2p = &b;  //基类指针指向了派生类p->oper1();  //不是虚函数,仍时基类oper1p->oper2();  //是虚函数构成多态,是派生类的oper2return 0;
}

运行结果过如下,重点关注是否为虚函数时函数调用的区别。

构成虚函数的必要条件:
函数返回类型一样,参数表一样,函数名一样,同时需要关键字vitrual,缺一不可。

class Basic
{vitrual  void p(){ 函数体};
}
class Direved :public Basic //构成虚函数的多态
{void p(){ 函数体};
}
class Basic
{void p(){ 函数体};
}
class Direved :public Basic //不构成虚函数
{void p(){ 函数体};
}
class Basic
{vitrual  void p(){ 函数体};
}
class Direved :public Basic //不构成虚函数
{void p(int a){ 函数体};
}
class Basic
{vitrual  void p(){ 函数体};
}
class Direved :public Basic //不构成虚函数
{double p(){ 函数体};
}

(5)C++纯虚函数
1.纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0”

virtual void funtion()=0

1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。
2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。

Class animals
{virtual void mingjiao() ; //动物基类,到底是什么动物呢,该怎么鸣叫?当无法合理的给予基类定义虚函数时,常用纯虚函数。{}
}

为了解决上述问题,引入了纯虚函数的概念

Class animals
{virtual void mingjiao()=0;
}

则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。
注意含有纯虚函数的类,不能直接声明对象!!!!!!!!

(6)多态性 实现的两种方式
a、编译时多态性:通过重载函数实现
b、运行时多态性:通过虚函数实现。

C++ 重载运算符 继承 多态 (超详细)相关推荐

  1. new是不是c语言运算符优先级表,C语言运算符优先级列表(超详细)

    <C语言运算符优先级列表(超详细)>由会员分享,可在线阅读,更多相关<C语言运算符优先级列表(超详细)(7页珍藏版)>请在人人文库网上搜索. 1.本篇文章是对C语言中运算符的优 ...

  2. c语言表达式的计算优先级,C语言运算符优先级(超详细)

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 C语言运算符优先级(超详细) 当想找哪个运算符优先级高时,很多时候总是想找的就没有,真让人气愤!现在,终于有个我个人觉得非常全的,分享给大家,欢迎拍砖! ...

  3. java多态的简单例子_要JAVA的简单例子,继承\多态的,详细讲解运行的每一步

    java中的多态是动态绑定的,也就是说在编译期不能确定一个方法的执行体是哪个方法(在继承中重写的方法).执行果支委会根据在堆上分配的的引用去寻找方法体,所以产生你你所不想要的结果是正常的也是正确的.改 ...

  4. 【面向对象】一文了解Java继承(超详细、超有趣)

    目录 引子 何为继承 超类和子类 继承的实现 子承父业 类的继承层次 类的继承路径 青出于蓝--方法重写 创新驱动发展 命名冲突 后继无人 血脉相连--protected修饰符 引子 在具体讲解之前, ...

  5. Java面向对象——继承(超详细讲解)

    一.继承的基本概念 被继承的类称为父类(超类),继承父类的类都称为子类(派生类) 继承是指一个对象直接使用另一个对象的属性和方法,但是能继承非私有的属性和方法: Java只能实现单继承,即一个类只能有 ...

  6. C++阶段03笔记02【类和对象(封装、对象的初始化和清理、对象模型和this指针、友元、运算符重载、继承、多态)】

    C++| 匠心之作 从0到1入门学编程[视频+课件+笔记+源码] 目录 1.内存分区模型 2.引用 3.函数提高 4.类和对象 4.1.封装 4.1.1.封装的意义 --实例1:设计圆类 --实例2: ...

  7. 音视频开发(十九):运算符重载、继承、多态、模版

    目录 类和对象的重要知识点 运算符重载 继承 多态 模版 一.类和对象的重要知识点 1.1 深拷贝与浅拷贝 浅拷贝:简单的赋值拷贝操作,拷贝构造 深拷贝:在堆区重新申请空间,进行拷贝操作 1.2 th ...

  8. 音视频开发系列(46)运算符重载、继承、多态、模版

    一.类和对象的重要知识点 1.1 深拷贝与浅拷贝 浅拷贝:简单的赋值拷贝操作,拷贝构造 深拷贝:在堆区重新申请空间,进行拷贝操作 1.2 this指针 this指针指向被调用的成员函数所属的对象. 本 ...

  9. 笔记②:牛客校招冲刺集训营---C++工程师(面向对象(友元、运算符重载、继承、多态) -- 内存管理 -- 名称空间、模板(类模板/函数模板) -- STL)

    0618 C++工程师 第5章 高频考点与真题精讲 5.1 指针 & 5.2 函数 5.3 面向对象(和5.4.5.5共三次直播课) 5.3.1 - 5.3.11 5.3.12-14 友元 友 ...

最新文章

  1. 实体框架高级应用之动态过滤 EntityFramework DynamicFilters
  2. webbench 代码阅读
  3. FONT Awesome 图标
  4. Vue实现Todo List
  5. xtrabackup 官方原理
  6. Java8 Lambdas:解释性能缺陷的排序
  7. html css a标签的应用
  8. 被马云逼上绝路,睡了12年宾馆!中国最狠会计,拿下4600亿
  9. 【Java 学习笔记】 抽象类和接口
  10. LoadRunner安装
  11. Visual Studio调试之避免单步跟踪调试模式
  12. echarter: ECharts的R语言接口(一)
  13. eclipse目录改名,子目录及JAVA文件同步更改
  14. 第一次网络渗透实验报告
  15. X509Certificate证书如何获取16位长度serial number?
  16. Springboot毕设项目M11463家居网9m26y(java+VUE+Mybatis+Maven+Mysql)
  17. element-ui 图标太少解决方案
  18. 最易被误读的十大职业排行榜
  19. python数据汇总_Python,将数据框中的每日数据汇总到每月和每季度
  20. 一键领取php,新款引流必备一键领取名片赞PHP单页源码

热门文章

  1. php ttf 字体 url,window_TTF字体文件如何安装 TTF文件打不开解决方法,TTF文件是Windows系统下的字体文 - phpStudy...
  2. newduba首页怎么去掉_京喜小程序首页瘦身实践
  3. Timer与ScheduledExecutorService间的选择
  4. 03 php,PHP 03 选择结构
  5. iOS 常用公共方法
  6. ?Web开发者需要知道的CSS Tricks
  7. 文件、目录——Linux基本命令(5)
  8. Apache中的Order Allow,Deny用法详解
  9. Oracle数据库分页的三种方法
  10. 老罗学习MVC之旅:MVC组件分析