且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

C++继承三之纯虚函数pure virtual function

更新时间:2021-07-26 06:20:13

在C++中我们可以将一些类的共性编写到一个抽象的类中叫他抽象类(ABC abstract base class)
这个类中必须包含一个纯虚函数,抽象类不能定义出对象,但是可以作为其他类的基类。在抽象
类中可以对纯虚函数进行定义也可以不定义,但是注意纯虚函数一般是通过抽象类派生出来的派
生类的差异性函数原型,及不能在抽象类中实现的函数。那么抽象类的特点为:
1、至少包含一个纯虚函数
2、纯虚函数可以定义也可以不定义,但是一般是派生类之间的差异函数不能实现的函数
3、抽象类不能用于定义对象,但是可以声明抽象类的指针和引用
4、抽象类包含析构函数、构造函数。
5、纯虚函数包含虚函数的所有特点,比如向上转换时候基类指针自适应、通过vtbl
   (virtual function table)
   实现等。


那么下面说明一下纯虚函数,纯虚函数可以包含定义也可以不包含定义,当然前面说过既然成为
纯虚函数一般是不能在抽象类中实现的函数
实际上在虚函数原型中
后面加上 = 0 即可如:
vritual test(int a) = 0 ;
可以将抽象ABC类看做一种必须的接口,派生类覆盖其纯虚函数,这样迫使派生类遵守
ABC类的接口规则,让设计人员能够制定接口约定,这样确保从抽象ABC类继承的所有的
派生类支持抽象类的约定的功能接口.
我们还是以C++ Primer Plus列子的头文件作为说明

点击(此处)折叠或打开

  1. #include<iostream>
    #ifndef ACCTABC_H_
    #define ACCTABC_H_
    #include<string>
    using namespace std;


    class AcctABC
    {
            private:
                string fullName;
                    long acctNum;
                    double balance;
            protected:
                    struct Formatting
                    {
                            ios_base::fmtflags flag;
                        streamsize pr;
                    };
                    const string& FullName() const{
                            return fullName;
                    }
                    long AcctNum() const {
                            return acctNum;
                    }
                    Formatting SetFormat() const;
                    void Restore(Formatting& f) const;
            public:
                    AcctABC(const string& s="Nullbody",long an= -1,double bal= 0.0);
                    void Deposit(double amt);
                    double Balance() const{return balance;};
                    virtual void Withdraw(double amt) = 0; //pure virtual function
                    virtual void ViewAcct() const = 0;//pure virtual function
                    virtual ~AcctABC(){}
    };


    class Brass:public AcctABC
    {
            public:
                    Brass(const string& s="Nullbody",long an=-1,double bal = 0.0):AcctABC(s,an,bal){}
                    virtual void Withdraw(double amt); //redefine pure virtual function 
                    virtual void ViewAcct() const;     //redefine pure virtual function
                    virtual ~Brass(){};
    };


    class BrassPlus:public AcctABC
    {
            private:
                    double maxLoan;
                    double rate;
                    double owesBank;
            public:
                    BrassPlus(const string& s="Nullbody",long an = -1,double bal=0.0,double ml = 500,double r=0.10);
                    BrassPlus(const Brass& ba,double ml=500,double r=0.1);
                    virtual void ViewAcct() const;//redefine pure virtual function
                    virtual void Withdraw(double amt);//redefine pure virtual function
                    void ResetMax(double m){maxLoan=m;}
                    void ResetOwes(){owesBank=0;}
                    virtual ~BrassPlus(){}
    };
    #endif

显然Brass和BrassPlus中包含了很多相同点,我们将他们
抽象出来,但是他们的不同点是
virtual void Withdraw(double amt);
virtual void ViewAcct() const;
实现的不同,并且brassPlus中多了一些数据成员
所以我们抽象出了AcctABC包含了共同点,
对实现不同的函数Withdraw和ViewAcct定义为
纯虚函数
virtual void Withdraw(double amt) = 0; //pure virtual function
virtual void ViewAcct() const = 0;//pure virtual function
让他随后的继承类中自己实现