15 多态和虚函数
15.1 向上转型
数据类型的转换,编译器会将小数部分直接丢掉(不是四舍五入)
int a = 66.9;printf("%d\n", a);//66float b = 66;printf("%f\n", b);//66.000000
· 只能将将派生类赋值给基类(C++中称为向上转型): 派生类对象赋值给基类对象、将派生类指针赋值给基类指针、将派生类引用赋值给基类引用
· 派生类对象赋值给基类对象,舍弃派生类新增的成员;派生类指针赋值给基类指针,没有拷贝对象的成员,也没有修改对象本身的数据,仅仅是改变了指针的指向;派生类引用赋值给基类引用,和指针的一样。、
上转型后通过基类的对象、指针、引用只能访问从基类继承过去的成员(包括成员变量和成员函数),不能访问派生类新增的成员
15.2 多态
不同的对象可以使用同一个函数名调用不同内容的函数。
· 静态多态性-在程序编译时系统就决定调用哪个函数,比如函数重载和静态多态性
· 动态多态性-在程序运行过程中动态确定调用那个函数,通过虚函数实现的。
15.3 虚函数
实现程序多态性的一个重要手段,使用基类对象指针访问派生类对象的同名函数。
· 将基类中的函数声明为虚函数,派生类中的同名函数自动为虚函数。
· 声明形式:virtual 函数类型 函数名 (参数列表);
· 构造函数不能声明为虚函数,析构函数可以声明为虚函数。
class A{public:
virtual void show()
{
cout <
}};class B: public A{public:
void show()
{
cout <
}};int main(){
B b;
b.show();//B show
A *pA = &b;
pA->show();//B show 如果show方法前没用virtual声明为虚函数,这里会输出A show
system("pause");
return 0;}
15.4 纯虚函数
在基类中不执行具体的操作,只为派生类提供统一结构的虚函数,将其声明为虚函数。
class A{public:
virtual void show() = 0;};class B: public A{public:
void show()
{
cout <
}};
抽象类:包含纯虚函数的类称为抽象类。由于纯虚函数不能被调用,所以不能利用抽象类创建对象,又称抽象基类。
16 运算符重载
所谓重载,就是赋予新的含义。函数重载(Function Overloading)可以让一个函数名有多种功能,在不同情况下进行不同的操作。运算符重载(Operator Overloading)也是一个道理,同一个运算符可以有不同的功能。
· 运算符重载是通过函数实现的,它本质上是函数重载。
允许重载的运算符
运算符名称
运算符
双目算术运算符
+、-、*、、、%
关系运算符
==、!=、、<=、>=
逻辑运算符
||、&&、!
单目运算符
+、-、*(指针)、&(取地址)
自增自减运算符
++、–
位运算符
|、&、-、……、<>
赋值运算符
=、+=、-=、*=、/=、%=、&=、!=、^=、<<= 、>>=
空间分配和释放
new、delete、new[]、delete[]
其他运算符
()(函数调用) 、->(成员访问)、->*(成员指针访问)、,(逗号)、
· 不允许重载的运算符
运算符名称
运算符
成员访问运算符
.
成员指针访问运算符
. *
域运算符
::
长度运算符
sizeof()
条件运算符
?:
16.1 定义
重载运算符遵循的规则:
· 不可以自己定义新的运算符,只能对已有的C++运算符重载。
· 不能改变运算符运算对象的个数。
· 不能改变运算符的优先级和结合性
· 应与标准类型运算功能相似,避免影响可读性。
一般格式:
函数类型 operator运算符(参数列表){
函数体}//举个栗子:定义一个向量类,通过运算符重载,可以用+进行运算。class Vector3{public:
Vector3();
Vector3(double x,double y,double z);public:
Vector3 operator+(const Vector3 &A)const;
void display()const;private:
double m_x;
double m_y;
double m_z;};
Vector3::Vector3() :m_x(0.0), m_y(0.0), m_z(0.0) {}
Vector3::Vector3(double x, double y,double z) : m_x(x), m_y(y), m_z(z) {}//运算符重载
Vector3 Vector3::operator+(const Vector3 &A) const{
Vector3 B;
B.m_x = this->m_x + A.m_x;
B.m_y = this->m_y + A.m_y;
B.m_z = this->m_z + A.m_z;
return B;}void Vector3::display()const{
cout<
16.2 形式
运算符重载的形式有两种:重载函数作为类的成员,重载函数作为类的友元函数
根据运算符操作数的不同:双目运算符作为类成员函数,单目运算符作为类的成员函数,双目运算符作为类的友员函数,单目运算符作为类的友元函数。
· 双目运算符作为友元函数时需要制定两个参数。
· 运算符重载函数作为类成员函数可以显式调用。
class Vector3{public:
Vector3();
Vector3(double x,double y,double z);public:
Vector3 operator+(const Vector3 &A)const;
Vector3 operator++();
friend Vector3 operator-(const Vector3 &v1, const Vector3 &v2);
friend Vector3 operator--(Vector3 &v);
void display()const;private:
double m_x;
double m_y;
double m_z;};
Vector3::Vector3() :m_x(0.0), m_y(0.0), m_z(0.0) {}
Vector3::Vector3(double x, double y,double z) : m_x(x), m_y(y), m_z(z) {}//运算符重载
Vector3 Vector3::operator+(const Vector3 &A) const{
Vector3 B;
B.m_x = this->m_x + A.m_x;
B.m_y = this->m_y + A.m_y;
B.m_z = this->m_z + A.m_z;
return B;}
Vector3 Vector3::operator++(){
this->m_x ++;
this->m_y ++;
this->m_z ++;
return *this;}void Vector3::display()const{
cout<
Vector3 operator-(const Vector3 &v1,const Vector3 &v2){
Vector3 B(v1.m_x - v2.m_x, v1.m_y - v2.m_y, v1.m_z - v2.m_z);
return B;}
Vector3 operator--( Vector3 &v){
v.m_x--;
v.m_y--;
v.m_z --;
return v;}int main(){
Vector3 v1(1, 2, 3);
Vector3 v2(2, 3, 2);
++v1;//v1.operator++(); 作为类成员函数可以显式调用
v1.display();
--v2;
v2.display();
Vector3 v3 = v1 + v2;// v1.operator+(v2);作为类成员函数可以显式调用
v3.display();
Vector3 v4 = v1 - v2;
v4.display();
return 0;}
16.3 常用运算符的重载
1.自增自减:
//前置运算符 ++a --aoperator++()operator--()operator++(Vector3 &v)operator--(Vector3 &v)//后置运算符 a-- a++operator++(int)operator--(int)operator++(Vector3 &v,int)operator--(Vector3 &v,int)
2.赋值运算符:
String& String::operator=(String &s){
if(this!=&s)
{ </