c++第五次作业:关于多态
关于多态
一、什么是多态
同样的消息被不同类型的对象接收时导致的不同的行为。对加法而言,如果是浮点数和整型数据相加,就要先将整型转换为浮点型在进行加法运算,这就是典型的多态。
二、关于多态的实现
1.编译时的多态
编译过程中确定同名操作的对象。
2.运行时的多态
在程序运行过程中动态确定操作所指具体对象。
运算符重载
1.主要优点
改变现有运算符的操作方式,以用于类类型,使得程序看起来更直观。
2.重载规则
a.只能重载c++已有的运算符(除了少数几个外都可以重载)。 b.重载之后运算符的优先级和结合性不变。 c.一般来说,重载的功能与原有功能类似,不能改变原运算符的操作对象个数,同时至少要有一个操作对象是自定义类型。 d.规定:类属关系运算符".",成员指针运算符".*",作用域分辨符"::",三目运算符"?:"是不能重载的。 ### 3.重载的形式 #### 重载为类的非静态成员函数 ##### a.一般语法形式返回类型 operator 运算符(形参表)
{
函数体
}
b.形参表
函数的参数个数比原来的操作数个数少一个(后置"++","--"除外)。因为第一个操作数会被作为函数调用的目的对象,函数体中可以直接访问第一个操作数成员。
c.具体实现(以自增自减为例实现)
#include"pch.h"
#include<iostream>
using namespace std;
class Point//定义一个Point类
{
public:
Point(int x,int y):x(x),y(y)
{}
//前置,单目运算所以没有形参
//前置实现之后结果是左值,并且在实现的时候要实现数据共享,所以传引用
Point& operator++();
Point& operator--();
//后置,有一个int参数仅用于区分前置与后置
Point operator++(int);
Point operator--(int);
void show()
{
cout << "the result is " << x <<";"<<y<< endl;
}
private:
int x,y;
};
//类的非静态函数成员实现
Point& Point::operator++()
{
x++;
y++;
return *this;
}
Point& Point::operator--()
{
x--;
y--;
return *this;
}
Point Point::operator++(int)
{
Point old = *this;
x++;
y++;
return old;
}
Point Point::operator--(int)
{
Point old = *this;
x--;
y--;
return old;
}
int main()
{
Point po(6,7);
po++.show();//6,7
po--.show();//7,8
po.show();//6,7
(--po).show();//5,6
(++po).show();//6,7
return 0;
}
重载为非成员函数
a.一般语法形式
返回类型 operator 运算符(形参表)
{
函数体
}
b.关于访问权限
在实现运算符重载时,有时需要访问运算符参数所涉及类的私有成员,这时可以把该函数声明为类的友元函数。
c.形参表
参数个数与原操作数个数相同。
d.具体实现(以复数类为例实现)
#include"pch.h"
#include<iostream>
using namespace std;
class Complex
{
public:
Complex(double real=0.0, double image=0.0) :real(real), image(image)
{
}
//友元函数实现
friend Complex& operator++(Complex &c1);
friend Complex operator++(Complex &c1,int);
void show()
{
cout << "(" << real << "," << image << ")" << endl;
}
private:
double real, image;
};
Complex& operator++(Complex &c1)
{
c1.real++;
c1.image++;
return c1;
}
Complex operator++(Complex &c1, int)
{
Complex c2 = c1;
++(c1);
return c2;
}
int main()
{
Complex a(3.0, 4.0);
Complex b(2.0, 5.0);
(b++).show();//2,5
b.show();//3,6
(++a).show();//4,5
return 0;
}
虚析构函数实现多态
关于它的实现
为了正确的调用对象的析构函数,一般要求具有层次结构的最原始的基类的析构函数定义为虚函数,因为在delete一个抽象类指针的时候,必须要通过虚函数才能找到真正的析构函数。
#include"pch.h"
#include<iostream>
using namespace std;
class Base
{
public:
Base()
{}
virtual ~Base()//虚析构函数
{
cout << "destrutor of Base" << endl;
}
};
class Derived :public Base
{
public:
Derived()
{}
~Derived()
{
cout << "destrutor of Derived" << endl;
}
};
int main()
{
//先生成Base对象,然后生成Derived对象,返回派生类地址给基类指针
Base *p = NULL;
p = new Derived;
delete p;
return 0;
}
结果展示
如果基类析构函数不是虚函数,则不会动态绑定到派生类的析构函数。如果上述基类的析构函数不是虚函数,则有
纯虚函数以及抽象类
抽象类
关于抽象类
带有纯虚函数的类。它的主要作用是通过它为一个类族建立一个公有的接口,使它们能够更有效地发挥多态特性。
抽象类派生
如果派生类给出所有纯虚函数的实现,这个派生类就可以定义自己的对象,因而不再是抽象类;如果派生类并没有给出所有纯虚函数的实现,这时的派生类仍然是一个抽象类。
抽象类的特点
不能对其实例化。也就是说不能定义一个抽象类的对象,但是可以定义一个抽象类的指针和引用。
纯虚函数
声明格式
virtual 函数类型 函数名(参数表)=0;
注意点
如果将析构函数声明为纯虚函数,必须给出它的实现,因为派生类的析构函数体执行完后需要调用基类的纯虚函数。