C++ 多态性

何为多态性?

相同的函数在不同环境下功能不同,例如‘<<‘在标准输入输出里是流,在运算中则是移位。’+‘在俩整数之间是直接相加,当一个数为浮点数,一个为整数时,则还要将整数转化为浮点数再相加。

面对对象的多态性可以分为四种

1)重载多态

     如类的成员函数重载。

2)强制多态

     如’+‘运算符。将类型强制转化

3)包含多态

      同样的操作可用于一个类型及其子类型。

4)参数多态

     通过给出不同的类型参数,使得一个结构有多种类型


C++多态的表现形式主要有函数的重载,运算符的重载和虚函数。


函数重载

C++允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同,也就是说用同一个运算符完成不同的运算功能。

这就是重载函数。重载函数常用来实现功能类似而所处理的数据类型不同的问题。

#include<iostream>
using namespace std;
class Clock
{
public:
    Clock(int newH, int newM, int newS);    // 构造函数
    Clock()                                 //构造函数,重载
    {
        hour=0;
        minute=0;
        second=0;
    }
    void setTime(int newH, int newM, int newS);
    void showTime(){
        cout<<hour<<" "<<minute<<" "<<second<<endl;
    }
private:
    int hour,minute,second;
};
Clock::Clock(int newH, int newM, int newS)
{
    hour=newH;
    minute=newM;
    second=newS;
}
int main()
{
    Clock m1;                //参数不同,功能不同   
    Clock m2(1,2,3);         
    m1.showTime();
    m2.showTime();
}

结果

0 0 0
1 2 3

运算符重载

运算符函数定义的一般格式为

数据类型 operator<运算符符号>(<参数表>)
{
    <函数体>
}

以下运算符不能重载

1)对象访问运算符    " . "

2)成员指针原算符   " .* "

3)作用域运算符      " :: "

4) " sizeof " 运算符

5) 三目运算符        “ ? ”


合法的运算符重载有四个限制

1) 重载以后的运算符不能改变运算符的优先级和结合性

2)重载以后的运算符不能改变运算符操作数的个数及语法结构

3)重载以后的运算符操作数至少有一个是自定义类型的。

4)重载运算符函数通常不能有默认的参数


#include<iostream>
using namespace std;


class A{
public:
	A(int a=0,int b=0):a(a),b(b){}
	int a;
	int b;
	A operator+(A c)     //+运算符重载
        {
	    return A(a+c.b,b+c.a);
        }
	void show()
	{
	    cout<<a<<" "<<b<<endl;
	}
};


int main()
{
	A a0(10,2);
	A a1(3,8);
	A a2=a0+a1;
	a2.show();
	return 0;
}

结果

18 5



虚函数

不同于其二者,虚函数是动态多态,而函数重载和运算符重载是静态重载。

静态多态在编译时就能知道函数调用地址,而动态多态须在运行时才知道调用地址。


运行时多态性须满足三个条件

1)父类的包含虚函数

2)子类的虚函数必须和父类的虚函数声明一致

3)通过父类的指针,或者引用访问虚函数实现动态多态

虚函数声明格式

virtual 返回类型 函数名(形参表)
{
    函数体
}

虚函数的几个特点

1)当父类的析构函数被定义为虚函数,那么其派生类的析构函数也为虚函数

2)使用虚函数时,存在子类公有继承父类才有意义

3)当父类的函数被定义为虚函数,那么其派生类里的同名函数也为虚函数

4)虚函数必须是所在类的成员函数,不能是友元函数,也不能是静态成员函数

5)当类中包含虚函数时,不管虚函数有几个,他们一共只占4个字节大小

#include<iostream>
using namespace std;

class A{
public:
	int a;

	A(){
		cout<<"begin A"<<endl;
	    a=1;
	}

	void show(){
		cout<<"A.a="<<a<<endl;
	}

	virtual ~A(){                       //虚函数
		cout<<"over A"<<endl;
	}

};

class C:public A{
public:
	C(){
		cout<<"begin C"<<endl;
		a=22;
	}
	~C(){
		cout<<"over C"<<endl;
	}
};

int main()
{
	A *p=new C;    //C类无名对象
	p->show();
 	delete p;   //回收无名对象
}

结果


begin A
begin C
A.a=22
over C
over A

这里我们使A类的析构函数为虚函数,倘若A类的析构函数不是虚函数,则结果不同


begin A
begin C
A.a=22
over A

可以看到,其派生类的析构函数没有运行到;

因为类中的虚函数,当访问到时,为一起访问其派生类的同名覆盖函数


纯虚函数

纯虚函数是虚函数的一种特例,包含纯虚函数的类称为抽象类,其不可以定义对象,只能作为父类。

其形式一般为

virtual 返回值类型 函数名 (参数表)=0;




猜你喜欢

转载自blog.csdn.net/wjb123sw99/article/details/77970766