现在有基类Quote和派生类Bulk_quote
Quote.h
#include<string>
using namespace std;
class Quote
{
private:
string bookNo;
protected:
double price = 0.0;
public:
Quote()=default;
Quote(const string &book, double sales_price):bookNo(book), price(sales_price){}
string isbn() const {return bookNo;}
virtual double net_price(std::size_t n) const{//虚函数是希望派生类进行重新的定义
return n*price;
}
virtual ~Quote() = default;
};
Bulk_quote.h
#include"Quote.h"
class Bulk_quote:public Quote
{
private:
/* data */
std::size_t min_qyt = 0;
double discount = 0;
public:
Bulk_quote(/* args */) = default;
Bulk_quote(const string&, double, size_t,double);
double net_price(size_t) const override;
};
test.cpp
#include"Bulk_quote.h"
int main(){
Quote item; //Quote对象
Bulk_quote bulk; //Bulk_quote对象
Quote *p = &item; //p指向Quote对象item
p = &bulk; //p指向bulk的Quote部分
Quote &r = bulk; //r绑定到bulk的Quote部分
}
这种转换被称为派生类到基类的转换,这种隐式特性意味着我们可以把派生类对象或者派生类的引用用在需要基类引用的地方;同样的,也可以把派生类对象的指针用在需要基类指针的地方。
动态类型和静态类型
test.cpp
在使用存在继承关系的类型时, 必须将一个变量或其他表达式的静态类型与该表达式表示对象的动态类型区分开来。
表达式的静态类型在编译时总是已知的,它是变量声明时的类型或表达式生成的类型;
动态类型则是变量或表达式表示内存中的对象的类型。
以这个print_total的函数为例子。
double print_total(ostream &os,const Quote &item, size_t n){
double ret = item.net_price(n);
os << "ISBN: " << item.isbn() << "# sold: "<<n<<" total due: " <<ret << std::endl;
return ret;
}
通过形参我们直到item的静态类型是Quote&,它的动态类型依赖于item绑定的实参。
如果我们传递一个Bulk_quote对象给print_total,那么它的动态类型就是Bulk_quote。