转换与继承--《C++ primer》笔记
派生类到基类的转换
基本上可以直接转,就提取派生类的基类部分就行了,其余的“切掉”(忽略)
01.//派生类和基类的转换,想把派生类对象转成基类对象,基本上是各种直接间接的“复制”,通过copy-constructor 和operator=等形式,把派生类对象的基类部分赋予新对象
02.#include<iostream>
03.class Item_base{};
04.class Bulk_item : public Item_base{};//注意此处,如果换成protecte和private,用户代码不能将派生类型对象转换为基类对象。
05.class D2 : public Bulk_item{};
06.int main(){
07. Item_base item1; //object of base type
08. Bulk_item bulk; //object of derived type
09. //ok:uses Item_base::Item_base(const Item_base&) constructor
10. //Item_base item2(bulk); //bulk is "sliced down" to its Item_base portion
11. //ok:calls Item_base::operator=(const Item_base&)参数是基类的引用,把派生类的基类部分做原本复制或赋值给新对象
12.
13. //不太明白什么叫使用转换,什么叫访问转换
14. D2 d2;
15. //public,用户代码和后代类都可以使用派生类到基类的转换
16. item1 = bulk; //bulk is "sliced down" to its Item_base portion
17. Item_base item3(d2);
18.
19. Bulk_item bulk2(d2);//语言容易误导,说protected继承的话,后续派生类的成员可以转换为基类类型,指的是这个直接基类Bulk_item,不是间接基类
20.}
21.class Derived;
22.class Base {
23. Base(const Derived&);//create a new Base from a Derived
24. Base &operator=(const Derived&);
25.};
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");
}