派生类到基类的转换
基本上可以直接转,就提取派生类的基类部分就行了,其余的“切掉”(忽略)
//派生类和基类的转换,想把派生类对象转成基类对象,基本上是各种直接间接的“复制”,通过copy-constructor 和operator=等形式,把派生类对象的基类部分赋予新对象
#include<iostream>
class Item_base{};
class Bulk_item : public Item_base{};//注意此处,如果换成protecte和private,用户代码不能将派生类型对象转换为基类对象。
class D2 : public Bulk_item{};
int main(){
Item_base item1; //object of base type
Bulk_item bulk; //object of derived type
//ok:uses Item_base::Item_base(const Item_base&) constructor
//Item_base item2(bulk); //bulk is "sliced down" to its Item_base portion
//ok:calls Item_base::operator=(const Item_base&)参数是基类的引用,把派生类的基类部分做原本复制或赋值给新对象
//不太明白什么叫使用转换,什么叫访问转换
D2 d2;
//public,用户代码和后代类都可以使用派生类到基类的转换
item1 = bulk; //bulk is "sliced down" to its Item_base portion
Item_base item3(d2);
Bulk_item bulk2(d2);//语言容易误导,说protected继承的话,后续派生类的成员可以转换为基类类型,指的是这个直接基类Bulk_item,不是间接基类
}
class Derived;
class Base {
Base(const Derived&);//create a new Base from a Derived
Base &operator=(const Derived&);
};
BaseToDerived
从基类到派生类的转换.因为包含关系,基类是不能直接自动转换为派生类对象的,除非间接(也就是利用基类的副本初始化派生类的基类部分,其余随便弄)
//基类到派生类的转换,是不可能自动发生的,因为兼容问题,派生类有基类部分,基类不可能有派生类部分
//所以要有条件的转换,说白了就是复制基类,利用基类部分给派生类的基类部分赋值,其他地方自动初始化一下
#include<iostream>
class Item_base {};
class Bulk_item : public Item_base {};
int main(){
/*Item_base base;
Bulk_item* bulkP = &base; //error:can't convert base to derived
Bulk_item& bulkRef = base; //error:can't convert base to derived
Bulk_item bulk = base; //error:can't convert base to derived
*/
//更惊讶的是,即使原本是Bulk_item,因为指针“强制转换”成Item_base,再转成Bulk_item也不允许了
Bulk_item bulk;
Item_base *itemP = &bulk; //ok:dynamic type is Bulk_item
Item_base item;
//Bulk_item *bulkP = itemP; //error:can't convert base to derived
//解决办法,强制转换(在知道这种情况,知道这样转换安全的前提下),dynamic_cast和dynamic_cast,后边介绍dynamic_cast
//Bulk_item *bulkP = static_cast<Bulk_item*>(itemP);//本身是派生类,只是指针“认为”基类的,可以再转换回来
//Bulk_item *bulkP = static_cast<Bulk_item*>(&item);
Bulk_item bulkP = static_cast<Bulk_item>(item);
//Bulk_item *bulkP = dynamic_cast<Bulk_item*>(itemP);
}
构造函数和复制控制:
派生类构造函数调用基类构造函数来初始化基类
#include<iostream>
class Item_base{//非派生类,一切正常
public:
Item_base(const std::string &book = "", double sales_price = 0.0) :
isbn(book), price(sales_price) {}
private:
std::string isbn;
double price;
};
/*只是隐式的调用Item_base的default constructor初始化对象的基类部分
class Bulk_item : public Item_base {//
public:
Bulk_item() : min_qty(0), discount(0.0) {}
private:
size_t min_qty;
double discount;
};
*/
//显式
class Bulk_item : public Item_base {
public:
Bulk_item(const std::string &book = "", double sales_price = 0.0,
std::size_t qty = 0, double disc_rate = 0.0 ) :
Item_base(book, sales_price), min_qty(qty), discount(disc_rate) {}
private:
size_t min_qty;
double discount;
};
int main(){
//有默认实参,可以输入四种情况
Bulk_item bulk1("0-201-82470-1", 50, 5, .19);
Bulk_item bulk2("0-201-82470-1", 50, 5);
Bulk_item bulk3("0-201-82470-1", 50);
Bulk_item bulk4("0-201-82470-1");
}
//直接间接的初始化,找到了,特例是通过派生类构造函数的函数体初始化,能给基类成员直接初始化。
//只能初始化直接基类,间接的就不行了 is not a direct base of class...
//书中号称派生类构造函数可以给基类public或protected成员赋值,HOW?试不出来does not have any field named 'discount'
//~~!!!!~~~~是在派生类构造函数的“函数体”内初始化基类成员--见quantity的初始化(即使把利用基类构造函数间接初始化quantity的语言删了也可以)
#include<iostream>
class Item_base{//非派生类,一切正常
public:
Item_base(const std::string &book = "", double sales_price = 0.0) :
isbn(book), price(sales_price) {}
double net_price(std::size_t) const;
private:
std::string isbn;
double price;
};
class Disc_item : public Item_base {
public:
Disc_item(const std::string& book = "", double sales_price = 0.0, std::size_t qty = 0.0, double disc_rate = 0.0) :
Item_base(book, sales_price), quantity(qty), discount(disc_rate) { }
std::size_t getQty() { return quantity; }
protected:
std::size_t quantity; //purchase size for discount to apply
double discount; //fractional discount to apply
};
//discount kicks in when a specified number of copies of same book are sold
//the discount is expressed as a fraction to use to reduce the normal price
class Bulk_item : public Disc_item {
public:
Bulk_item(const std::string& book = "", double sales_price = 0.0, std::size_t qty = 0, double disc_rate = 0.0) :
Disc_item(book, sales_price, qty, disc_rate) {quantity = qty + 8;}
//redefines base version so as to implement bulk purchase discount policy
double net_price(std::size_t) const;
};
int main(){
Bulk_item bulk;
std::cout << bulk.getQty() << std::endl;
}
15.15题,因为他英文那些东西,分类就搞不清楚,有book,有record,又视频video,有视频游戏video game的,还children's puppet,没法理解,随便分类,意思一下就行了。
pe15_16.cpp
练习题
其他的都简单,不知到下边这个怎么样,也是属于没遵守接口,直接访问id了吧,同构造函数体内初始化基类成员稍有不同,性质应该差不多。
struct C4 : public Base {
C4(int val) : Base(id + val) { }
};