相关内容:
- 派生类和基类的自动转换只针对指针或引用类型(对象转换会存在问题,代码中有体现)。 只有指针和引用支持自动类型转换,同时,也只有指针和引用才可以静态类型和动态类型不同,这两个配合就完成了c++的最重要的多态。
- 在公有派生的情况下,派生类的指针可以直接赋值给基类指针。但即便基类指针指向的是一个派生类的对象,也不能通过基类指针访问基类没有而派生类中有的成员。
- 基类的指针不能赋值给派生类的指针。但是通过强制类型转换,也可以将基类指针强制转换成派生类指针后再赋值给派生类指针。只是在这种情况下,程序员需要保证被转换的基类指针本来就指向一个派生类的对象,这样才是安全的,否则很容易出错。
- 在对象之间不存在类型转换。
- 基类到派生类不存在自动转换,可以通过强制类型转换,如static_cast 或dynamic_cast转换成。
代码相关内容:
- 派生类->基类:引用转换/指针转换;对象转换;
- 基类->派生类:基类到派生类的自动转换不存在;想要转换需要强制转换;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using namespace std;
class Item_base
{
public:
int x;
Item_base(const std::string &book = "",
double sales_price = 0.0) :isbn(book), price(sales_price) {}
std::string book() const
{
return isbn;
}
// virtual:定义为虚函数,则在派生类中可以对其进行重新定义;
virtual double net_price(size_t n) const
{
return n * price;
}
private:
string isbn;
protected:
double price;
};
class Bulk_item : public Item_base
{
public:
// 派生类的构造函数;
Bulk_item(const std::string &book = "", double sales_price = 0.0, size_t qty = 0,
double disc_rate = 0.0) :Item_base(book, sales_price), min_qty(qty), discount(disc_rate) {}
void test()
{
// cout << x << endl;
cout << price << endl; // 成员函数,可以使用父类中的protected成员;
// cout << isbn << endl; // 但是不能使用父类中的private成员;
}
void test2(const Bulk_item &d, const Item_base &b)
{
//cout << d.x << endl;
cout << d.price << endl;
//cout << b.x << endl; // public成员没问题;
//cout << b.price << endl; // 错误;protected成员可以在类的内部使用或者是对它的友元使用,可以被继承,但是不能被调用;
}
// 只有虚函数才能够重写;
double net_price(size_t cnt) const
{
if (cnt >= min_qty) //如果购买的数量大于最小打折数量,则打折;
return cnt * (1 - discount) *price;
else
return cnt * price;
}
private:
size_t min_qty;
double discount;
};
// 此处传入的是对象 item;
void print_total_1(ostream &os, const Item_base item, size_t n)
{
os << "ISBN: " << item.book() << "\tnumber sold: " << n << "\ttotal price: " << item.net_price(n) << endl;
}
// 此处传入的是指针 *item;
void print_total_2(ostream &os, const Item_base *item, size_t n)
{
os << "ISBN: " << item->book() << "\tnumber sold: " << n << "\ttotal price: " << item->net_price(n) << endl;
}
// 此处传入的是引用 &item;
void print_total_3(ostream &os, const Item_base &item, size_t n)
{
os << "ISBN: " << item.book() << "\tnumber sold: " << n << "\ttotal price: " << item.net_price(n) << endl;
}
int main()
{
Item_base item("asdf", 9.9);
Bulk_item item2("asdf", 9.9, 10, 0.12);
// 所以在动态绑定,多态的时候,不要用对象转换,可以用指针转换或者引用转换;
print_total_1(cout, item, 10);
print_total_1(cout, item2, 10); // 此处传入的 item 是派生类,派生类到基类可以自动转换;这是对象转换,对象转换有问题!(此处应该打折,但是没有打折)
cout << endl;
print_total_2(cout, &item, 10); // 传入的就是基类,没有问题;
print_total_2(cout, &item2, 10); // 此处传入的 item 是派生类,派生类到基类可以自动转换;这是指针转换,打折了,没有问题。
cout << endl;
print_total_3(cout, item, 10); // 传入的就是基类,没有问题;
print_total_3(cout, item2, 10); // 此处传入的 item 是派生类,派生类到基类可以自动转换;这是引用转换,打折了,没有问题。
// item2 = item; //错误;
Bulk_item *p = static_cast<Bulk_item *>(&item); //如果想将基类转换为派生类,可以强制转换,但是一般不用这个特性;
cout << p->net_price(10) << endl;
return 0;
}代码执行结果:
参考链接:
c++ 派生类向基类转换的可访问性
C++基类和派生类指针的相互赋值和转换