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;

注意点

如果将析构函数声明为纯虚函数,必须给出它的实现,因为派生类的析构函数体执行完后需要调用基类的纯虚函数。

猜你喜欢

转载自www.cnblogs.com/summer-00/p/11741285.html