继承——虚函数

简介: 继承——虚函数

虚函数的定义

在基类与派生类那里我们介绍了当我们使用基类的引用或指针调用一个虚成员函数的时候会执行动态绑定,因为我们在运行之前也并不知道会调用哪个版本的虚函数,因为我们只有在运行的时候才能确定我们将会调用哪一个版本的虚函数,所以我们在定义的时候必须给每一个虚函数提供定义。

对函数的调用在运行时才被解析

#include<iostream>
using namespace std;
class Quote
{
public:
    string book_ISBN;//书的编号
    double price;
    Quote(const string& name,double p,string No):book_name(name),price(p),book_ISBN(No)
    {
    }
    virtual double net_price(size_t n) const
    {
        return n*price;
    }
    virtual string get_ISBN() const
    {
        return book_ISBN;
    }
    Quote(double p,string No):price(p),book_ISBN(No)
    {}
    virtual ~Quote()=default;
private:
    string book_name;
};
class Bulk_Quote:public Quote
{
private:
    size_t min_qry;
    double discount;
    string book_name;
public:
    Bulk_Quote(const string& name,string book_ISBN,double price,size_t qry,double dis):Quote(price,book_ISBN),book_name(name),min_qry(qry),discount(dis)
    {}
    double net_price(size_t n) 
    {
        if(n>=min_qry)
        price=price*discount;
        return n*price*discount;
    }
    string get_ISBN() const
    {
        return book_ISBN;
    }
    ~Bulk_Quote()
    {}
};
void Total_price(ostream& os,const Quote& item,size_t n)
{
    double ret=item.net_price(n);
    os<<"ISBN:   "<<item.get_ISBN()<<endl;
    os<<"net_price:   "<<ret<<endl;
}
int main()
{
    Quote base("fengxu",10.78,"0-201-82470a-1");
    Bulk_Quote derived("fengxu","0-201-82470a-1",10.78,10,0.7);
    Total_price(cout,derived,40);
    Total_price(cout,base,10);
    return 0;
}

如上代码所示,虽然我们指定的类型时Quote的引用,但是当我们传进derived时,item会绑定在Bulk_Quote类型的对象上,这时调用则是Bulk_Quote::net_price,而传入base时,则是与Qutoe绑定,此时调用的则是Quote::net_price.

final和override关键词

在我们定义派生类的时候,有时候我们如果在派生类里面定义了一个名字和虚函数相同但是形参列表顺序不同的函数,在编译器看来这么写其实是合法的,但是这个函数和虚函数没有任何关系,这也意味着我们原先需要覆盖的虚函数并没有被覆盖,就实际要求来看这时候发生了错误。

这时候就要拿出我们的override关键词了,当我们用override标记了这个函数,如果这个函数并没有成功覆盖已经存在的虚函数,此时编译器就会报错:

class Quote
{
public:
    Quote() =default;
    Quote(double size_price,const string& number):size_price(size_price),m_number(number) 
    {
    }
    string IseN()
    {
        return m_number;
    }
    virtual double Total_price(double size_price,int n)
    {
        return n*size_price;
    }
    virtual ~Quote() =default;
    private:
    string m_number;
    protected:
    double size_price=0.0;
};   
class Bulk_Qutoe:public Quote
{
public:
    Bulk_Qutoe()=default;
    Bulk_Qutoe(double,const string&,int,double);
    double Total_price(int book_number,double size_price)  const override;
private:
    double discount;
    int book_number;
    string book_name;
};
class Bulk_Qutoe:public Quote
{
public:
    Bulk_Qutoe()=default;
    Bulk_Qutoe(double,const string&,int,double);
    double Total_price(int book_number,double size_price)  const ;
private:
    double discount;
    int book_number;
    string book_name;
};

对于上述Bulk_Quote的俩种不同写法,前者会报错,而后者则是合法的,充分的说明了override的作用。

final关键词的作用则是当我们把某个函数标记为final后,之后所有试图覆盖该函数的操作都是非法的。·

虚函数和默认实参

和其他函数一样,虚函数也有默认实参,如果调用了默认实参。则实参值由本次调用的静态类型决定。

通俗一点来说,当我们使用基类的引用或者指针来调用函数的时候,此时使用的是基类的默认实参,哪怕当前使用的是派生类里面的函数也是这样,此时传进去的仍然是基类函数定义的默认实参,如果派生类重新定义使该函数被覆盖,此时用派生类的引用或者指针对函数进行调用,传递进去的就是派生类定义的默认实参。

回避虚函数的机制

在一些特定的场景下,我们希望对虚函数的调用不要进行动态绑定,而是我们可以自行决定我们使用虚函数的某一个特定的版本,这时候我们可以使用作用域运算符来实现执行虚函数的某一个特定版本,实例代码如下:

double undiscounted=basep->Quote::net_price(42);

这里baseP是一个指向基类的指针。

虚函数的回避机制常常用于派生类已经被覆盖的虚函数需要调用其基类版本,如果不使用回避机制会造成函数的无限递归。

相关文章
|
7天前
|
C++
C++一分钟之-虚函数与抽象类
【6月更文挑战第21天】在C++中,虚函数与抽象类是多态的基础,增进类间耦合与灵活性。虚函数实现动态绑定,抽象类定义不可实例化的接口。关键点包括:记得使用`virtual`,避免滥用虚函数,确保派生类实现纯虚函数。抽象类不能直接实例化,派生类必须实现所有纯虚函数。通过实例代码学习和实践,能更好地掌握这些概念以优化代码设计。
20 2
|
8天前
|
数据安全/隐私保护
继承——基类与派生类
继承——基类与派生类
|
1月前
|
Serverless C++
C++多态性、虚函数、纯虚函数和抽象类知识网络构造
C++多态性、虚函数、纯虚函数和抽象类知识网络构造
|
1月前
|
C++ 编译器 存储
|
1月前
|
C++
C++|多态性与虚函数(2)|虚析构函数|重载函数|纯虚函数|抽象类
C++|多态性与虚函数(2)|虚析构函数|重载函数|纯虚函数|抽象类
|
9月前
|
编译器 C++
C++中的多态和虚函数
#include <iostream> using namespace std; //基类People class People{ public: People(char *name, int age); void display(); protected: char *m_name; int m_age; }; People::People(char *name, int age): m_name(name), m_age(age){} void Peopl
41 1
C++中的多态和虚函数
|
11月前
|
存储 编译器 C++
<c++>虚函数与多态 | 虚函数与纯虚函数 | 多态的实现原理 | 虚析构函数
<c++>虚函数与多态 | 虚函数与纯虚函数 | 多态的实现原理 | 虚析构函数
109 0
|
10月前
|
C++
|
11月前
|
C++
<c++> 类的继承 | 基类与派生类 | 构造函数与析构函数
<c++> 类的继承 | 基类与派生类 | 构造函数与析构函数
109 0
|
C++
基类派生类多态虚函数?
通常在层次关系的根部有一个基类,其他类则直接或间接的从基类继承而来,这些继承得到的类称为派生类。基类负责定义在层次关系中所有类共同拥有的成员,而每个派生类定义各自特有的成员。
98 0