转换和继承,虚函数
Understanding conversions between base and derived classes is essential to
understanding how object-oriented programming works in C++.
理解基类和派生类之间的转换是不可缺少的 理解面向对象编程在。
Like built-in pointers, the smart pointer classes (§12.1, p. 450) support the
derived-to-base conversion—we can store a pointer to a derived object in a
smart pointer to the base type.
像内置指针,智能指针类支持 导出到基类的转换能够存储一个指向派生类对象的一个
基类类型的指针。
class Quote
{
public:
    Quote()=default;
    Quote(const string &book, double sales_price):bookNo(book), price(sales_price)
     {cout<<"Quote gouzhao function"<<endl;}
    string isbn() const {return bookNo;}
    //返回指定数量的项目总销售价格
    //派生类将重写应用不同的折扣算法
    virtual double net_price(size_t n) const {return n*price;}
    virtual ~Quote()=default;   //动态链接析构函数
private:
    string bookNo;  //这本书的isbn号
protected:
    double price=0.0;       //不打折的价格
};
//继承,怎样继承?
class Bulk_quote : public Quote
{
public:
    Bulk_quote()=default;
    Bulk_quote(const string & book, double p, size_t qty, double disc)
    : Quote(book, p), min_qty(qty), discount(disc)
    {cout<<"Bulk_quote construct function"<<endl;}
    //重写虚函数
    double net_price(size_t n) const override {cout<<"double net_price(size_t)"<<endl; return n*price;}
    //再次说明,请声明函数后一定要记得定义它。不然我这是出了各种莫名其妙的错误!
//    ~Bulk_quote2(){cout<<"~Bulk_quote2()"<<endl;}
private:
    size_t min_qty=0;
    double discount=0.0;
};
void fun1()
{
    Quote base;
//    Bulk_quote* bulkP=&base;    错误不能把基类转换成派生类
//    Bulk_quote& bulkRef=base;    同上
    Bulk_quote bulk;
    Quote *itemP=&bulk;     //派生类转换成基类
//    Bulk_quote *bulkP=itemP;    error:基类到派生类
}
void fun2()
{
    Bulk_quote bulk;    //派生类
    Quote item(bulk);   //调用基类Quote的赋值构造函数
    item=bulk;          // calls Quote::operator=(const Quote&)拷贝赋值运算符
}
double print_total(ostream &os, const Quote &item, size_t n)
{
    //依据不同的对象来绑定到这个參数的类型
    //这里引用Quote::net_price 或 Bulk_quote::net_price
    double ret=item.net_price(n);
    os<<"ISBN: "<<item.isbn()   //调用 Quote::isbn
      <<" # sold: "<<n<<" total due: "<<ret<<endl;
    return ret;     //这里上面的Quote參数是能够接受Quote或者Bulk_quote类型的
}
void fun3()
{
    Quote base("0-201-82470-1", 50);
    print_total(cout, base, 10);    //调用Quote的net_price
    Bulk_quote derived("0-201-82470-1", 50, 5, 0.19);
    print_total(cout, derived, 10); //调用Bulk_quote的net_price
    base=derived;   //吧quote类型的部分复制到base
    base.net_price(20);
}
这也就非常自然地解释了为什么函数不能通过返回值不同来重载。由于程序在调用函数时非常有可能不关心返回值,编译器就无法从代码中看出程序在调用的是哪个函数了。
(3)       覆盖的函数前必须加keywordVirtual;
重载和Virtual没有不论什么瓜葛,加不加都不影响重载的运作。
struct B
{
    virtual void f1(int) const;
    virtual void f2();
    void         f3();
};
struct D1 : B   //这是什么继承?
{
    void    f1(int) const   override;   //ok能够覆盖
//    void    f2(int) override;   error没有f2(int)这个虚函数
//    void    f3()    override;      //error:f3()不是虚函数
//    void    f4()    override;       error:没有f4()这个虚函数
};
struct D2 : B
{
    //从B继承f2,f3之后我们override f1
    void f1(int) const final;   //之后派生类无法覆盖f1
};
struct D3 : D2
{
    void f2();
//    void f1(int) const; //注意:这个函数是被final修饰的函数
};
void fun4()
{
    cout<<"there is fun4"<<endl;
    Quote *baseP;
    double undiscounted = baseP->Quote::net_price(42);
}
接口是软件产品最有价值的资源。
设计接口比实现接口须要耗费更昂贵的成本。
因此,要将接口保护起来,
以免在针对客户需求改动实现的时候,程序猿不小心把接口破坏掉。
2.引入抽象基类和纯虚函数方便实现C++的多态特性。
能够用抽象基类的指针去调用子类对象的方法。
3.非常多时候。很多基类被实例化是不合理的。
比如“形状”这个基类,被实例化之后反而会让人相当费解,
所以干脆将“形状”这个类定义为抽象类,由它派生出正方形,三角形等子类。
基类的纯虚函数必须有“=0”,但不一定没有函数的实现,仅仅是不能直接内嵌在类中。
class Disc_quote : public Quote
{
public:
    Disc_quote()=default;
    Disc_quote(const string & book, double price, size_t qty, double disc):
        Quote(book, price), quantity(qty), discount(disc) {cout<<"Disc_quote构造函数"<<endl;}
    double net_price(size_t) const = 0; //纯虚函数
protected:
    size_t quantity=0;
    double discount=0.0;
};
void fun5()
{
    cout<<"there is fun5"<<endl;
//    Disc_quote discount;    //error:Disc_quote是一个抽象类,含有纯虚函数没法实例化
    Bulk_quote bulk;        //ok,这个里面没有纯虚函数,不是抽象类
}
class Bulk_quote2 : public Disc_quote
{
public:
    Bulk_quote2()=default;
    //直接初始化
    Bulk_quote2(const string& book, double price, size_t qty, double disc):
        Disc_quote(book, price, qty, disc) {}
    double net_price(size_t) const override;    //覆盖纯虚函数
};


版权声明:本文博客原创文章,博客,未经同意,不得转载。
原文:http://www.cnblogs.com/hrhguanli/p/4620886.html