基类和派生类之间的转换实例教程

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

9
10 11
pa = &a;
12
pb = &b;
13
14
//pb = pa;
//错误。不能用基类指针给派生类指针赋值。
15
pb = (B*)pa;
//可以强制转换,但是非常不安全。
pb‐>display();
//出现安全问题,p无法访问,因为a中没有p成员
注意到我们使用强制转换时,当派生类添加了基类中不存在的成员时,会出现安全问题。 pb­>display();会调用派生类的display函数,但是它指向的内存是基类对象a的内存,p不存在。会出现严重后果。
?
1
A a(3, 4);
2
B b(10, 20, 30);
3
A * pa;
4
4
B * pb;
5 6
// print2(a);
//错误。不能用基类对象给派生类引用赋值。
7
// print4(a);
//错误。不能用基类对象给派生类对象赋值。
8
// pb = &a;
//错误。派生类指针不能指向基类对象。
?
1
A a(3, 4);
2
// a.display();
3
4
B b(10, 20, 30);
5
5
// b.display();
6
7 8
A * pa;
9
// B * pb;
10
// pa = &a;
11 12
// pa‐>display();
13
// pb = &b;
14
// pb‐>display();
pa = &b; pa‐>display();
百度文库
//会输出 10 20
pa为基类指针,指向派生类对象是合法的,因为派生类对象也是基类对象。语句会输出派生类对象中基类部分。 注意:这里并不会调用派生类的display函数,调用的是基类的display函数,因为指针pa是基类指针,编译器在编译阶段只知道pa的类型。如果要实现调 用派生类的display函数,需要用到虚函数实现多态性。之后的文章会讲到。 进一步解释一下编译时和运行时的区别。 编译时编译器能知道pa的类型为A *,但是不知道它指向了哪个对象,假如有以下语句
pb = (B*)pa;
//可以强制转换,但是非常不安全。
pb‐>display();
//出现安全问题,p无法访问,因为a中没有p成员
system ( "pause" );
return 0;
}
切记:派生类对象是基类对象,派生类中包含有基类的成员。基类对象不是派生类对象,它不能包含派生类型的成员。 一、派生类到基类的转化 1.派生类对象地址赋值给基类指针 main函数中执行以下代码
本文实例讲解了C++中基类和派生类之间的转换。对于深入理解C++面向对象程序设计有一定的帮助作用。此处需要注意:本文实例讲解内容的前提是派生 类继承基类的方式是公有继承,关键字public。具体分析如下:
以下程序为讲解示例:
?
1
#include<iostream>
2
using namespace std;
75 76
B b(10, 20, 30);
77
// b.display();
78
79
A * pa;
80
B * pb;
81
81
pa = &a;
82 83
// pa‐>display();
84
pb = &b;
85
// pb‐>display();
// pa = &b; // pa‐>display();
52 53
{
54
b.display();
55
}
56
57 58
void print3(A a)
59
{
60
a.display();
61 62
}
63
64
void print4(B b)
65
{
66 67
b.display();
68
}
69
70
int main()
71 72
{
73
A a(3, 4);
74
// a.display();
33
int p;
34
35
};
36
37
37
void B::display()
38 39
{
40
A::display();
41
cout << "p = " << p << endl;
42 43
}
44
45
void print1(A& a)
46
{
47 48
a.display();
49
}
50
51
void print2(B& b)
?
1
A a(3, 4);
2
B b(10, 20, 30);
3 print1(b);
//会输出 10 20
形参为基类引用,实参为派生类对象,派生类对象也是基类对象,可以赋值给基类引用。输出派生类中基类部分。 注意:此时对象本身并未复制,b仍然是派生类对象,前面说过了引用就是一个指针。 3.派生类对象赋值给基类对象。
// pb = &a;
//错误。派生类指针不能指向基类对象。
// print1(b); // print2(a); // print3(b); // print4(a);
//错误。不能用基类对象给派生类引用赋值。 //错误。不能用基类对象给派生类对象赋值。
// pb = pa;
//不能用基类指针给派生类指针赋值。
21
22
cout << "n = " << n << endl;
23
}
24
25
class B : public A
26
27
{
28
public :
29
B( int m1, int n1, int p1) :A(m1, n1), p(p1){}
30
31
void display();
32
private :
?
1
A a(3, 4);
2
B b(10, 20, 30);
3
print3(b);
派生类对象基类部分被复制给形参。 注意:实际上没有从派生类对象到基类对象的直接转换。对基类对象的赋值或初始化,实际上在调用函数,初始化时调用构造函数,赋值时调用赋值操作符。 二、基类到派生类的转化 切记:这种转换有可能引发严重的安全问题,编写代码时不要使用。没有基类到派生类的自动转换,原因在于基类对象只能是基类对象,不能包含派生类型的成员。 如果允许用基类对象给派生类对象赋值,那么就可以试图使用该派生类对象访问不存在的成员。
?
1
A a(3, 4);
2
B b(10, 20, 30);
3
4
A* pa;
5
int number;
6
cin >> number;
7
8
if (number >= 0)
9
pa = &a;
else
pa = &b;
pa指向的对象类型依赖于输入,运行时才输入,所以编译器是没有办法知道pa指向哪个类型的。
2.派生类对象赋值给基类引用 引用跟指针基本没有区别,引用本质上是指针,是个指针常量,具体可以参照我的另一篇C++中的引用和指针的联系和区别 main函数中执行以下代码
3
4
5
class A
6
{
7
public :
8
9
A( int m1, int n1):m(m1), n(n1){}
10
void display();
11
private :
12
13
int m;
14
int n;
15
};
16
17
18
void A::display()
19
{
20
cout << "m = " << m << endl;
相关文档
最新文档