C++之多态

多态概述

一种对象为了接口重用而呈现的多重形态。

多态分类

多态分为两类:

  • 静态多态:函数重载、运算符重载和模板
  • 动态多态:派生类和虚函数

静态多态

函数重载

概念:函数名相同,形参数量、类型、顺序不同,返回值可同可不同

作用:接口重用,避免名字污染,提高可读性。

注意:形参无法通过const区分开,比如int max(int a)和int max(const int a)是一样的;而指针和引用可以通过const区分开,int max(int &a)和int max(const int &a)是不一样的。

底层实现:C语言中没有函数重载,因为编译器在编译的时候只会在函数名前加"_",所以两个函数名相同,编译出错。
在C++中,虽然函数名相同,但是它们在符号表中生成的名字不同,会同时加入返回值类型和形参类型来命名,所以编译可以通过。

运算符重载

概念:对已有的运算符进行重新定义,赋予其另一种功能,以适应不同的数据类型。
运算符重载的实质是函数重载,可以重载为普通函数,也可以重载为类成员函数。运算符重载的基本形式如下:

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

例子:

#include <iostream>
using namespace std;
class Complex
{
public:
	Complex(double real = 0.0, double imag = 0):m_real(real), m_imag(imag) { }
	
	// 重载-号的类成员函数
	Complex operator-(const Complex &c)
	{
		return Complex(m_real-c.m_real, m_image-c.image);
	}

	void PrintComplex()
	{
		cout<<m_real<<","<<m_image<<endl;
	}

	//重载运算符+号的普通函数,定义为友元函数
	friend Complex operator+(const Complex &a, const Complex &b);

private:
	double m_real;
	double m_imag;
};

Complex operator+(const Complex &a, const Complex &b)
{
	return Complex(a.m_real+b.m_real, a.m_image+b.m_image);
}

int main()
{
	Complex a(1,1);
	Complex b(2,2);
	Complex c;

	c = a + b;	//等价于c=Complex operator+(a,b)
	c.PrintComplex();
	
	c = a - b;	//等价于c=a.operator-(b)
	c.PrintComplex();
	
	return 0;
}

输出结果:
3,3
-1,-1

注意:

  • 重载-号和+号的运算符函数返回类型是Complex而不是Complex&
    因为函数执行之后,需要返回一个新的对象给到左值
  • 重载-号和+号运算符函数参数表是const Complex &a,是常引用,而不是Complex a
    因为如果是Complex a,在入参时就会调用默认的赋值(拷贝)构造函数,产生了一个临时变量,这会增大开销,所以采用引用。采用const,防止引用对象被修改

模板(泛型)

函数模板

概念:函数模板就是建立一个通用函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为模板。

编译器对函数模板进行二次编译:在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。

用法:

#include <iostream>
using namespace std;
template <typename type1, typename type1>
type Max(type1 a, type2 b)
{
	return a>b?a:b;
}
void main()
	cout << Max(5.5, 'a') << endl;

参数匹配优先级:
在有多个函数和函数模板名字相同的情况下,一条函数调用语句,到底应该被匹配成哪个函数或对哪个模板的调用呢?C++编译器遵循以下规则:

  1. 先找参数完全匹配的普通函数
  2. 再找参数完全匹配的模板函数
  3. 然后找实参经过自动类型转换后能够匹配的普通函数
  4. 上面的都找不到则报错

函数模板的局限性:模板并不是真正通用的代码,对于一些自定义的数据,模板有时候不能实现效果。可以通过具体化实现对自定义数据类型进行操作
例如:

template<class T>
bool myCompare(T &a, T &b)
{
	if(a == b)
		return true;
	else
		return false;
}

template<> myCompare<Person>(Person &a, Person &b)
{
	if(a.m_name == b.m_name && a.m_age == b.m_age)
		return true;
	return false;
}
类模板

类模板概念:用于解决多个功能相同、数据类型不同的类需要重复定义的问题。

基本用法:
类模板的定义形式:
template <class 类型参数1, class 类型参数2, …>
class 类模板
{
成员变量和成员函数
};

用类模板定义对象:
类模板<真实类型参数表> 对象名(构造函数实参表);

比如:

template <typename T1, typename T2>
class Student
{
private:
	T1 m_name;
	T2 m_score;
public:
	Student() = default;
	Student(T1 name, T2 score):m_name(name), m_score(score) {}
	Student(const Student<T1,T2> &s)
	{
		m_name = s.m_name;
		m_score = s.m_score;
	}
	void print_info();
}
template<typename T1, typename T2>
void Student::print_info()
{
	cout << m_name << endl;
	cout << m_score << endl;
}

void main()
{
	Student<string, double> s;
}

动态多态

即虚函数,具体详见C++之继承

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值