C++的多态性

       C++编程语言是一款应用广泛,支持多种程序设计的计算机编程语言。我们今天就会为大家详细介绍其中C++多态性的一些基本知识,以方便大家在学习过程中对此能够有一个充分的掌握。多态性可以简单地概括为“一个接口,多种方法”,程序在运行时才决定调用的函数,它是面向对象编程领域的核心概念。多态(polymorphism),字面意思多种形状。C++多态性是通过虚函数来实现的,虚函数允许子类重新定义成员函数,而子类重新定义父类的做法称为覆盖(override),或者称为重写。(这里我觉得要补充,重写的话可以有两种,直接重写成员函数和重写虚函数,只有重写了虚函数的才能算作是体现了C++多态性)而重载则是允许有多个同名的函数,而这些函数的参数列表不同,允许参数个数不同,参数类型不同,或者两者都不同。编译器会根据这些函数的不同列表,将同名的函数的名称做修饰,从而生成一些不同名称的预处理函数,来实现同名函数调用时的重载问题。但这并没有体现多态性。多态与非多态的实质区别就是函数地址是早绑定还是晚绑定。如果函数的调用,在编译器编译期间就可以确定函数的调用地址,并生产代码,是静态的,就是说地址是早绑定的。而如果函数调用的地址不能在编译器期间确定,需要在运行时才确定,这就属于晚绑定。那么多态的作用是什么呢,封装可以使得代码模块化,继承可以扩展已存在的代码,他们的目的都是为了代码重用。而多态的目的则是为了接口重用。也就是说,不论传递过来的究竟是那个类的对象,函数都能够通过同一个接口调用到适应各自对象的实现方法。

  最常见的用法就是声明基类的指针,利用该指针指向任意一个子类对象,调用相应的虚函数,可以根据指向的子类的不同而实现不同的方法。如果没有使用虚函数的话,即没有利用C++多态性,则利用基类指针调用相应的函数的时候,将总被限制在基类函数本身,而无法调用到子类中被重写过的函数。因为没有多态性,函数调用的地址将是一定的,而固定的地址将始终调用到同一个函数,这就无法实现一个接口,多种方法的目的了。

C++纯虚函数
 一、定义
  纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加“=0” 
  virtual void funtion()=0 
二、引入原因
   1、为了方便使用多态特性,我们常常需要在基类中定义虚拟函数。 
   2、在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。 
  为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重写以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。这样就很好地解决了上述两个问题。
三、相似概念
   1、多态性 
  指相同对象收到不同消息或不同对象收到相同消息时产生不同的实现动作。C++支持两种多态性:编译时多态性,运行时多态性。 
  a、编译时多态性:通过重载函数实现    b、运行时多态性:通过虚函数实现。 
  2、虚函数 
  虚函数是在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态覆盖(Override)
  3、抽象类 
  包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象

/*纯虚函数--规定了对外接口的统一形式,作为基类来使用*/ 
#include <iostream>
using namespace std;


class Base1{
	public:
		virtual void display() const = 0;//纯虚函数,0表示没有函数体 
}; 


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;            //覆盖基类的虚函数 
}; 
void Derived::display() const{
	cout << "Derived::display()" << endl;
}


void fun(Base1 *ptr){
	ptr->display();
}

int main(){
	Base2 base2;
	Derived derived;
	fun(&base2);
	fun(&derived); 
	return 0;
}

/*单目运算符"++"重载为成员函数对形式*/ 
/*语法规定:前置的单目运算符重载为成员函数时没有形参,而后置单目运算符重载为成员函数时需要有一个int型形参*/ 
#include <iostream>
using namespace std;

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(hour>=0 && hour<24 && minute>=0 && minute<60 && second>=0 && 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){//后置单目运算符重载,注意参数表中有整型参数,int用于区分是前置还是后置,无实质性作用。 
	Clock old = *this;
	++(*this);
	return old; 
} 

int main(){
	Clock myClock(23, 59, 59);
	cout << "Fist time output: ";
	myClock.showTime();
	cout << "Show myClock++: ";
	(myClock++).showTime();//先用再加1 
	cout << "Show ++myClock: ";
	(++myClock).showTime(); //先加1再用 
	return 0;
}
 



/*加减运算符的重载*/ 
#include <iostream>
using namespace std;


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 << ")" << endl;
} 
int main(){
	Complex c1(5, 4), c2(2, 10), c3;
	cout << "c1 = ";
	c1.display();
	cout << "c2 = ";
	c2.display();
	c3 = c1 - c2;
	cout << "c3 = c1 - c2 = ";
	c3.display();
	c3 = c1 + c2;
	cout << "c3 = c1 + c2 = ";
	c3.display();
	return 0;
}

/*虚函数实现运行的多态*/ 
#include <iostream>
using namespace std;

class Base1{
	public:
		virtual void display() const;//声明为虚函数后,都要在类外实现函数,不能写成内联函数,它不会在编译阶段调用display,而再运行时调用 
}; 
void Base1::display() const{
	cout << "Base1::display()" << endl;
}


class Base2: public Base1 {          //公有派生类的Base2的定义 
	public:
		virtual void display() const;//覆盖基类的虚函数 ,派生类可以不显式的用virtual声明虚函数,故派生类的virtual可以省略 
};
void Base2::display() const{
	cout << "Base2::display()" << endl;
}


class Derived: public Base2{
	public:
		virtual void display() const;//覆盖基类的虚函数 
}; 
void Derived::display() const{
	cout << "Derived::display()" << endl;
}

void fun(Base1 *ptr){
	ptr->display();
} 
int main(){
	Base1 base1;
	Base2 base2;
	Derived derived;
	fun(&base1);
	fun(&base2);
	fun(&derived);
	return 0;
}

/*虚析构函数*/ 
#include <iostream>
using namespace std;


class Base{
	public:
		virtual ~Base();
}; 
Base::~Base(){
	cout << "Base destructor" << endl;
}


class Derived:public Base{
	public:
		Derived();
		~Derived();
	private:
		int *p; 
};
Derived::Derived(){
	p = new int(0);
}
Derived::~Derived(){
	cout << "Derived destructor" << endl;
	delete p; 
}


void fun(Base *b){
	delete b;
}

int main(){
	Base *b = new Derived();
	fun(b); 
	return 0;
}

/*运算符重载为非成员函数--必须把操作数全部通过形参的方式传递给运算符重载函数*/ 

#include <iostream>
using namespace std;


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);//重载插入运算符<<  
		void display() const;
	private:
		double real;
		double imag; 	 
}; 

//下面的函数已经重载为类外的全局函数,故不用Complex Complex::operator+ 
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;
}

void Complex::display() const{
	cout << "(" << real << "," << imag << ")" << endl;
} 
int main(){
	Complex c1(5, 4), c2(2, 10), c3;
	cout << "c1 = ";
	c1.display();
	cout << "c2 = ";
	c2.display();
	c3 = c1 - c2;
	cout << "c3 = c1 - c2 = ";
	c3.display();
	c3 = c1 + c2;
	cout << "c3 = c1 + c2 = ";
	c3.display();
	return 0;
}



猜你喜欢

转载自blog.csdn.net/wangjian530/article/details/80462978