c++ 关于多态

前言:

        多态是面向对象三大特征之一,也是在面试的时候问的最多的问题。

1、概念

        简单来说,多态就是多种形态,当我们要完成某个行为的时候,不同的对象去完成时会产生不同的状态,这就叫做多态。多态就是同一个接口,不同功能的实现。

2、特点

        多态分为两种:静态多态和动态多态。在编译时的多态,就是静态多态,在运行时的多态,就是动态多态。

2.1 静态多态

        静态多态主要通过重载或者模板来实现的,就是要求在相同作用域下,函数名一样,参数列表不一样,可以是参数的类型不一样,也可以是参数数量不一样,当然给参数加const也可以实现重载,在编译的时候,通过实参来确定调用的,属于编译时多态,也就是静态多态。

        代码如下:

#include <iostream>
using namespace std;

int add(int a, int b)
{
	return a + b;
}
double add(double a, double b)
{
	return a + b;
}

template <typename T>
T add(T a, T b)
{
	return a + b;
}

int main()
{
	cout << add(10,20) << endl;          // 调用int add(int a, int b) 输出30
	cout << add(1.2,2.0) << endl;        // 调用double add(double a, double b) 输出3.2
	cout << add<char>('A', ' ') << endl; //调用模板函数  输出'a'
	cout << add<int>(5, 10) << endl;     //调用模板函数  输出15
    return 0;
}

        重载函数在c++中还有运算符重载,之后我再补充。

2.2 动态多态

        我们常说的C++的多态,默认主要说动态多态为主。动态多态最常见的用法就是声明基类的指针,使用该指针指向任意一个派生类的对象。

2.2.1 虚函数

概念:

        在类中声明为 virtual的成员函数,称为虚函数。虚函数是C++中用于实现多态的机制。核心理念就是通过基类访问派生类定义的函数。

        如果没有使用虚函数,基类指针只能调用基类的成员函数,不能调用派生类的成员函数。

代码:

class Base
{
public:
	void output()
	{
		cout << "Base::output()" << endl;
	}
};

class Derived : public Base
{
public:
	void output()
	{
		cout << "Derived::output()" << endl;
	}
};

int main()
{
	Derived derived;
	Base *base1 = &derived;
	base1->output();
	Base & base2 = derived; // 基类的引用也可以使用多态
	base2.output();
	return 0;
}

运行结果:

Base::output()
Base::output()

在基类的成员函数前加virtual关键字,把其声明为虚函数。有了虚函数,基类指针表现出了多种形态,这种现象称为多态

代码:

class Base
{
public:
	virtual void output() //成员函数声明前添加virtual关键字
	{
		cout << "Base::output()" << endl;
	}
};

class Derived : public Base
{
public:
	virtual void output() //派生类的函数不写virtual也能成为虚函数,但是为了代码清晰,建议写上
	{
		cout << "Derived::output()" << endl;
	}
};

int main()
{
	Derived derived;
	Base *base1 = &derived;
	base1->output();
	Base & base2 = derived; // 基类的引用也可以使用多态
	base2.output();
	return 0;
}

运行结果:

Derived::output()
Derived::output()

2.2.2 虚析构函数

        析构函数也可以定义为虚函数,如果基类的析构函数定义为虚析构函数,则派生类的析构函数就会自动成为虚析构函数。

        如果基类的指针指向派生类的对象,当用delete删除这个对象时,若析构函数不是虚析构函数,只会调用基类的析构函数,不会调用派生类的析构函数,会导致内存泄漏。

代码:

class Base
{
public:
	Base()
	{
		cout << "Base构造函数" << endl;
	}
	~Base()
	{
		cout << "Base析构函数" << endl;
	}
};

class Derived : public Base
{
public:
	Derived()
	{
		cout << "Derived构造函数" << endl;
	}
	~Derived()
	{
		cout << "Derived析构函数" << endl;
	}
};


int main()
{
	Base *base = new Derived;
	delete base;
	return 0;
}

运行结果:

Base构造函数
Derived构造函数
Base析构函数

        给基类的析构函数加上virtual关键字,使析构函数成为虚析构函数。

代码:

class Base
{
public:
	Base()
	{
		cout << "Base构造函数" << endl;
	}
	virtual ~Base() //添加virtual关键字
	{
		cout << "Base析构函数" << endl;
	}
};

        再次运行,运行结果如下:

Base构造函数
Derived构造函数
Derived析构函数
Base析构函数

2.2.3 虚函数表

        c++的虚函数是通过虚函数表来实现动态多态的。表里面存放了类中的虚函数地址信息。虚函数表指针放在对象的起始位置上。

class Base
{
public:
	int a;
	int b;
	virtual void fun1()
	{
		cout << "fun1" << endl;
	}
	virtual void fun2()
	{
		cout << "fun2" << endl;
	}
};

代码如下:

int main()
{
	Base base;
	cout << "当前对象所占空间大小:" << sizeof(base) << endl;
	cout << &base << endl;
	cout << &base.a << endl;
	cout << &base.b << endl;
	return 0;
}

运行结果:

当前对象所占空间大小:12
005DF984
005DF988
005DF98C

接下来,使用函数指针来调用类中的虚函数

代码如下:

int main()
{
	Base base;
	typedef void(*Test)();
	Test *vtaddr = (Test *)*(int*)&base;
	vtaddr[0]();
	vtaddr[1]();
	return 0;
}

运行结果:

fun1
fun2

2.2.4 纯虚函数

        纯虚函数是基类中只声明函数,没有实现,要求在派生类中定义的成员函数。

语法:

class 类名
{
访问权限:
    virtual 类型 函数名(形参列表) = 0; //无函数体
};

抽象类:

        1.有纯虚函数的类被称为抽象类或虚基类;

        2.抽象类不能被实例化(不能被定义为对象);

        3.从抽象类继承而来的派生类,可以不实现纯虚函数,如果不实现,派生类还是抽象类,也不可被实例化;

        4.可以声明抽象类的指针和引用。

声明如下抽象类:

class Base
{
public:
	int a;
	int b;
	virtual void fun1() = 0;
};

在派生类中实现纯虚函数

class Derived : public Base
{
public:
	void fun1()		//实现基类的纯虚函数
	{
		cout << "fun1()" << endl;
	}
};

int main()
{
	Base *base = new Derived; //可以声明抽象类的指针和引用
	base->fun1();
	delete base;
	return 0;
}

  • 13
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值