栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

C++学习多态

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

C++学习多态

文章目录
  • 1、多态性
  • 2、运算符重载
    • 注意:
        • 注意:
  • 3、虚函数
      • 实现动态多态的必要条件:
      • 注意:
          • 重载、重写、重定义的区别:
  • 4、纯虚函数和抽象类
  • 5、虚析构函数和纯虚析构函数
    • 何时会用虚析构函数?
    • 何时会用到纯虚析构函数?
    • 如何计算一个类对象的大小:
  • 6、模板
    • 1、函数模板
    • 2、类模板

1、多态性

多态性是指向不同的对象发送同一消息会产生不同的行为

举例:

按q 盲僧:天音波 压缩:斩钢闪

盲僧->q(); 压缩->q();

(1)运行期多态:动态多态,早绑定:虚函数

(2)编译器多态:静态多态,晚绑定:函数重载,运算符重载,模板

2、运算符重载

C++中的运算符只能对基本数据类型进行运算,无法对类对象进行运算

实现机制:

将指定的运算符表达式转换为运算符函数,运算对象转换为函数的参数

A a,b;

a + b ----> operator+(a,b) ---->调用—>a + b

注意:

(1)只能重载C++中已有的运算符,不能臆造新的

(2)不能改变运算符原有的优先级和结合性

(3)不能改变操作数个数

(4)经重载后的运算符,其操作数至少有一个是自定义类型

(5)可以重载除以下运算符以外的所有运算符:

. .* :: ?: sizeof

重载方式:

(1)重载为类成员函数

参数个数 = 原操作数个数 - 1(思考:为什么-1?因为this指针),除后置+±-外

(2)重载为友元函数

参数个数 = 原操作数个数

注意:

有些运算符只能重载为友元函数,有些运算符只能重载为类成员函数,有些运算符两种方式都可以。

= -> () [] 这四个运算符只能重载为类成员函数,不能重载为友元函数。

声明方式:

返回类型 operator运算符(参数);

如: operator+

C++中临时变量不能作为非const的引用参数

#include 
using namespace std;

void f(int &a)      //非const引用
{
 cout << "f(" << a  << ") is being called" << endl;
}

void g(const int &a) //const引用
{
 cout << "g(" << a << ") is being called" << endl;
}
int main()
{
    int a = 3, b = 4;
f(a + b);  //编译错误,把临时变量作为非const的引用参数传递了
    g(a + b);  //OK,把临时变量作为const&传递是允许的
}
3、虚函数

概念:在函数原型前加上virtual关键字,就变成了虚函数,如:virtual void fun();

作用:用来实现动态多态

实现原理:当基类指针或引用指向派生类对象时,如果是普通函数,则调用的是基类中的函数,如果是虚函数,则调用的是派生类中的函数

虚函数会在内存中生成虚函数表vtable,一个虚函数表对应一个虚表指针vptr

基类和派生类公用同一个虚函数表

实现动态多态的必要条件:

1、要有继承

2、要有虚函数的重写(覆盖) //重载、重写(覆盖)、重定义(隐藏)的区别?

3、基类指针或引用指向派生类对象

注意:

在派生类中不写virtual关键字,依然是虚函数

重载、重写、重定义的区别:

重载:同一作用域内有相同函数名,不同参数列表的函数(同一个类中)

重写(复写、覆盖):在派生类中,重新定义从基类继承而来的虚函数,并且函数名,参数,返回值必须一致(在基类和派生类中)

重定义(隐藏):在派生类中,重新定义从基类继承而来的函数,函数名相同,参数和返回值不同(在基类和派生类中),只要不构成重写就是重定义。

4、纯虚函数和抽象类

概念:在虚函数后面加上“=0”,就实现了纯虚函数,如:virtual void fun() = 0;

作用:在许多情况下,在基类不能对虚函数作出有意义的实现,那么就可以将这个虚函数设为纯虚函数,这样在基类中不用给出实现,实现就留给派生类自己,但是后面依然可以给出纯虚函数的实现。

抽象类:包含纯虚函数的基类叫做抽象类。抽象类不能实例化(创建对象),只为派生类提供接口,如果派生类继承了纯虚函数,依然没有给出实现,那么这个派生类还是抽象类。

5、虚析构函数和纯虚析构函数 何时会用虚析构函数?

当用基类指针指向派生类对象时,要通过基类指针来删除派生类对象时,那么要将基类的析构函数设为虚函数,否则调用基类的析构函数,不会调用派生类的析构函数,造成内存泄漏。但是不要无故的将析构函数设为虚函数,因为虚函数会占用内存

何时会用到纯虚析构函数?

当需要把一个基类设为抽象类时,需要引入纯虚函数,但此时又 没有 有意义的纯虚函数,那么就可以将析构函数设为纯虚析构函数。

为什么构造函数不能为虚函数?

虚函数对应虚函数表vtable,虚函数表是存在在对象的内存空间的,构造函数是在创建对象由系统自动调用,如果构造函数是虚函数,就在存在虚函数表中,但是此时对象还没分配空间,没有对应的虚函数表,所以构造函数不能为虚函数。

如何计算一个类对象的大小:

1、空类占一个字节

2、类中的函数(普通函数、静态函数、虚函数)都不占空间

3、虚函数本身不占空间,但是虚表指针占空间,所有虚函数公用一个虚表指针

4、普通成员数据占空间,静态成员数据不占空间

一个类的大小 >= 所有非静态成员数据大小的总和

5、有继承时,基类和派生类公用一个虚表指针

6、计算类对象大小时,也会按照字节对齐

7、多继承时,有几个基类就有几个虚表指针

8、虚继承时,会生成虚基表,对应的虚基表指针

一个类的大小 = 所有非静态成员数据大小的总和 + 虚表指针(多继承时有多个)+虚基表指针(多继承有多个)+对齐的字节数。

6、模板 1、函数模板

函数的重载可以实现一个函数名重用,但还是得写多个函数,用不同的参数实现多态。函数模板可以只写一个函数,就能实现多态。

声明方式:

template 或者 template

class和typename 可以相互互换

struct不能实现模板

template   //template 
T compare(T a,T b)
{
	return a>b?a:b;
}


int main(void)
{
	int a1 = 10,b1 = 20;
	float a2 = 10,b2 = 20;
	double a3 = 10,b3 = 20;
	
	cout << compare(a1,b1) << endl;
	cout << compare(a2,b2) << endl;
	cout << compare(a3,b3) << endl;
}
2、类模板
#include 
#include 

using namespace std;

template 
class A
{
	public:
		A(T1 a,T2 b)
		{
			this->a = a;
			this->b = b;
		}
		void show();
	private:
		T1 a;
		T2 b;
};

template 
void A::show()
{
	cout << a << endl;
	cout << b << endl;
}

int main(void)
{
	//A a(1,1.2);
	A a1(1,2);
	A a2(1.2,"123");
	A a3("abc","123");
	a1.show();
	a2.show();
	a3.show();
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1018809.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号