类-多态

1. 基本概念

多态性:

  • 操作接口具有表现多种形态的能力,能根据操作环境的不同采用不同的处理方式。
  • 一组具有相同基本语义的方法能在同一接口下为不同的对象服务。

实现方式:

绑定机制 绑定是将一个标识符名和一个存储地址联系在一起的过程。例如:虚函数的实现对应着虚表,每一个派生类都包含了一个指向虚表的指针,运行时根据对象的指针找到虚表指针,然后取出对应的函数

  • 静态绑定:编译阶段完成
  • 动态绑定:运行时完成

分类:

  • 静态多态性:运算符重载
  • 动态多态性:虚函数

2. 运算符重载

2.1 重载为类的成员函数

函数类型 operator 运算符(形参)
{
......
}
参数个数=原操作数个数-1 (后置++、--除外)

eg1:复数重载加法

class Complex {
public:
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) { }
//运算符+重载成员函数
Complex operator + (const Complex& c2) const;
//运算符-重载成员函数
Complex operator - (const Complex& c2) const;
void display() const; //输出复数
private:
double real; //复数实部
double imag; //复数虚部
};
Complex Complex::operator+(const Complex& c2) const {
//创建一个临时无名对象作为返回值
return Complex(real + c2.real, imag + c2.imag);
}
Complex Complex::operator-(const Complex& c2) const {
//创建一个临时无名对象作为返回值
return Complex(real - c2.real, imag - c2.imag);
}void Complex::display() const {
cout << "(" << real << ")+(" << imag << ")j" << endl;
}

eg2:时钟类重载自增。后置自增需要传递一个参数

class Clock {//时钟类定义
public:
Clock(int hour = 0, int minute = 0, int second = 0);
void showTime() const;
//前置单目运算符重载
Clock& operator ++ ();
//后置单目运算符重载
Clock operator ++ (int);
private:
int hour, minute, second;
};
Clock::Clock(int hour, int minute, int second) {
if (0 <= hour && hour < 24 && 0 <= minute && minute < 60
&& 0 <= second && second < 60) {
this->hour = hour;
this->minute = minute;
this->second = second;
}
else
cout << "Time error!" << endl;
}
void Clock::showTime() const { //显示时间
cout << hour << ":" << minute << ":" << second << endl;
}
Clock& Clock::operator ++ () {
second++;
if (second >= 60) {
second -= 60; minute++;
if (minute >= 60) {
minute -= 60; hour = (hour + 1) % 24;
}
}return *this;
}
Clock Clock::operator ++ (int) {
//注意形参表中的整型参数
Clock old = *this;
++(*this); //调用前置“++”运算符
return old;
}

2.2 重载为非成员函数

如果数据是类的private成员,需要将函数声明为友元函数

eg:复数重载加减法和输出流运算符

class Complex {
public:
Complex(double r = 0.0, double i = 0.0) : real(r), imag(i) { }
friend Complex operator+(const Complex& c1, const Complex& c2);
friend Complex operator-(const Complex& c1, const Complex& c2);
friend ostream& operator<<(ostream& out, const Complex& c);
private:
double real; //复数实部
double imag; //复数虚部
}; Complex operator+(const Complex& c1, const Complex& c2) {
return Complex(c1.real + c2.real, c1.imag + c2.imag);
}
Complex operator-(const Complex& c1, const Complex& c2) {
return Complex(c1.real - c2.real, c1.imag - c2.imag);
}
ostream& operator<<(ostream& out, const Complex& c) {
out << "(" << c.real << ", " << c.imag << ")";
return out;
}

3. 虚函数

  • 通过virtual关键字实现
  • 虚函数必须是非静态成员函数,也不能是内联函数(编一阶段必须定下来的)
  • 构造函数不能是虚函数,析构函数可以

eg1:

class Base1 {
public:
virtual void display() const; //虚函数
};
void Base1::display() const {
cout << "Base1::display()" << endl;
} class Base2: public Base1 {
public:
virtual void display() const;
};
void Base2::display() const {
cout << "Base2::display()" << endl;
} class Derived : public Base2 {
public:
virtual void display() const override;
};
void Derived::display() const {
cout << "Derived::display()" << endl;
}
void fun(Base1* ptr) {
ptr->display();
}

调用函数fun()时,能够根据指针的实际类型调用正确的函数

eg2:虚析构函数。使用了new运算符创建对象,然后要用对象指针释放空间

#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base(); //不是虚函数
};
Base::~Base() {
cout << "Base destructor" << endl;
}
class Derived : public Base {
public:
virtual ~Derived(); //不是虚函数
};
Derived::~Derived() {
cout << "Derived destructor" << endl;
}
void release(Base* p) {
delete p;
}
int main() {
Derived* pObj = new Derived();
release(pObj);
return 0;
}

基类和子类的析构函数都会被调用。如果析构函数非虚,那么只会调用基类的析构函数,子类中新增加的成员可能不会被释放,造成内存泄漏

4. 抽象类

定义:带纯虚函数的类是抽象类

纯虚函数:没有函数体的虚函数 virtual 函数类型 函数名(参数表) = 0;

抽象类作用

  • 抽象类为抽象和设计的目的而声明
  • 将有关的数据和行为组织在一个继承层次结构中,保证派生类具有要求的行为。
  • 对于暂时无法实现的函数,可以声明为纯虚函数,留给派生类去实现。

注意

  • 抽象类只能作为基类来使用。
  • 不能定义抽象类的对象。

5. overridefinal

  • override显式指明该函数是虚函数,编译器检查在基类中如果没有对应的函数,会报错
  • final用来避免类被继承,或是基类的函数被改写

【C++】类-多态的更多相关文章

  1. YTU 2979: MathBook类--多态

    2979: MathBook类--多态 时间限制: 1 Sec  内存限制: 128 MB 提交: 51  解决: 31 题目描述 Book类将自己的display函数设计为虚函数,从而通过父类指针调 ...

  2. python 全栈开发,Day21(抽象类,接口类,多态,鸭子类型)

    一.昨日复习 派生方法和派生属性 super 只有在子父类拥有同名方法的时候, 想使用子类的对象调用父类的方法时,才使用super super在类内 : super().方法名(arg1,..) 指名 ...

  3. python面向对象 : 抽象类(接口类),多态,封装(私有制封装)

    一. 抽象类(接口类) 与java一样, python也有抽象类的概念但是同样需要借助模块实现,抽象类是一个特殊的类, 它的特殊之处在于只能被继承, 不能被实例化. 从设计角度去看, 如果类是从现实对 ...

  4. c++中的类(class)-----笔记(类多态)

    1,多态是一种运行期绑定机制,通过这种机制,实现将函数名绑定到函数具体实现代码的目的.一个函数的名称与其入口地址是紧密相连的,入口地址是该函数在内存中的起始地址.如果对一个函数的绑定发生在运行时刻而非 ...

  5. 【学习笔记】--- 老男孩学Python,day18 面向对象------抽象类(接口类), 多态, 封装

    抽象类,接口类 Python没有接口这个概念 抽象类(接口类): 目的是制定一个规范 要学会归一化设计,有重复的东西就要想把它们合并起来 from abc import ABCMeta, abstra ...

  6. python day - 19 抽象类 接口类 多态 封装

    一. 抽象类接口类即制定一个规范 特点: 1.不可被实例化. 2.规范子类当中必须事先某个方法. 3.在python中有原生实现抽象类的方法,但没有原生实现接口类的方法. 例题:制定一个规范就是,子类 ...

  7. python(类多态)

    一.多态 (以封装和继承为前提)不同的子类调用相同的方法,产生不同的结果 class Dog(): def __init__(self,name): self.name = name def game ...

  8. python之7-2类的继承与多态

    类的继承的意思就如同父子关系一样,这个儿子继承了父亲的一切,但是在某些地方(属性)相同的时候,儿子的属性大于老子的属性(覆盖),最底层类,总会继承最接近它的那个类的属性init 类的多态总是和继承相连 ...

  9. python - class类 (六) 三大特性 - 多态

    多态的概念: # 多态的概念 # 指出了对象如何通过他们共同的属性和动作来操作及访问而不需考虑他们的具体的类 # 多态表明了动态绑定的存在,允许重载及运行时类型确定和验证. # 示例模拟: #水具有多 ...

随机推荐

  1. CF1473B String LCM 题解

    Content 如果一个字符串 \(s\) 由若干个字符串 \(t\) 拼接而成,则我们说 \(s\) 能被 \(t\) 整除.定义 \(s_1,s_2\) 的最短公倍串为可以同时被 \(s_1,s_ ...

  2. xfs文件系统修复方法https://blog.csdn.net/yuanfang_way/article/details/78700089

    首先尝试mount和umount文件系统,以便重放日志,修复文件系统,如果不行,再进行如下操作. 1.检查文件系统:先确保umount xfs_check /dev/sdd(盘符); echo $?  ...

  3. windows下apache安装 https配置。

    https://blog.csdn.net/jhope/article/details/78596066?utm_source=blogxgwz2 https://blog.csdn.net/tdcq ...

  4. django——django链接mysql数据库

    1.创建项目 django-admin startproject django_mysql 2.创建App python manage.py startapp app1 3.Mysql数据库配置 (1 ...

  5. 【LeetCode】643. 子数组最大平均数 I Maximum Average Subarray I (Python)

    作者: 负雪明烛 id: fuxuemingzhu 公众号:每日算法题 目录 题目描述 题目大意 解题方法 方法一:preSum 方法二:滑动窗口 刷题心得 日期 题目地址:https://leetc ...

  6. 【LeetCode】522. Longest Uncommon Subsequence II 解题报告(Python)

    [LeetCode]522. Longest Uncommon Subsequence II 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemin ...

  7. D. Water Tree

    D. Water Tree time limit per test 4 seconds memory limit per test 256 megabytes input standard input ...

  8. 1017 - Brush (III)

    1017 - Brush (III)   PDF (English) Statistics Forum Time Limit: 2 second(s) Memory Limit: 32 MB Sami ...

  9. [技术干货-算子使用] Mindspore 控制流中存在原地更新操作类副作用算子时循环值不更新问题记录

    关于mindspore 原地更新类算子的一点思考记录如下: 现象记录: 原始测试代码 错误结果复现: 分析: 如果在场景中加入42行的copy()操作此时cpu的结果就会正确,但是gpu的结果则不受c ...

  10. CS5265替代CH7211|Capstone CS5265芯片|替代CH7211芯片

    龙迅Chrontel的CH7211是一款Type-C转HDMI2.0半导体设备,可通过USB Type-C连接器将DisplayPort信号转换为HDMI/DVI.这款创新的基于USB Type-C的 ...