大胖的部落格
Just a note
C++博客
::
首页
::
新随笔
::
联系
::
聚合
::
管理
::
112 随笔 :: 0 文章 :: 3 评论 :: 0 Trackbacks
<
2009年5月
>
日
一
二
三
四
五
六
26
27
28
29
30
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
1
2
3
4
5
6
留言簿
给我留言
查看公开留言
查看私人留言
随笔分类
Algorithm(13)
(rss)
C#(13)
(rss)
C++(22)
(rss)
Design Pattern(23)
(rss)
Others(14)
(rss)
STL(9)
(rss)
Technical(2)
(rss)
UML(2)
(rss)
Win32(18)
(rss)
Reference
Windows XP command line
最新评论
1. re: 在TCL命令行中调用C函数
@Kenny
实在不好意思,时间太过久远,本人已好久没有接触TCL……
--大胖
2. re: 在TCL命令行中调用C函数
請問如何溝通array 變數
Q:1
tcl array in C
Q:2
C array in tcl
懇求指導
--Kenny
3. re: 在TCL命令行中调用C函数
谢谢!
--1232
多态与数组
当用父类指针指向子类对象数组时,用父类类型的指针对数组进行操作是不安全的。
因为数组里是连续分布的子类对象,父类和子类的大小不同,所以当用父类指针对数组进行操作时,会对数组空间重新按照父类大小进行切割。
#include
"
stdafx.h
"
#include
<
iostream
>
#include
<
Windows.h
>
#define
CLASS_NUM (5)
using
namespace
std;
class
Base
{
public
:
Base()
{
iBase
=
++
i;
}
virtual
~
Base()
{}
void
TestNonVirtual()
{
cout
<<
"
Base::NonVirtual:
"
<<
iBase
<<
endl;
}
virtual
void
TestVirtual()
{
cout
<<
"
Base::Virtual:
"
<<
iBase
<<
endl;
}
static
int
i;
int
iBase;
//
mark the object
}
;
int
Base::i
=
0
;
class
Derived:
public
Base
{
public
:
Derived()
{
iDerived
=
iBase
*
10
;
}
void
TestNonVirtual()
{
cout
<<
"
Derived::NonVirtual:
"
<<
iBase
<<
endl;
}
void
TestVirtual()
{
cout
<<
"
Derived::Virtual:
"
<<
iBase
<<
endl;
}
long
lDerived;
int
iDerived;
}
;
//
传入父类型数组
void
TestArray(Base b[])
{
int
i
=
0
;
while
(i
<
CLASS_NUM)
{
//
按父类型大小裁剪连续分布的子类型对象数组空间
b[i].TestNonVirtual();
++
i;
}
}
//
main
int
main(
int
argc,
char
*
argv[])
try
{
//
输出类的size
cout
<<
"
Size Of Base:
"
<<
sizeof
(Base)
<<
endl;
cout
<<
"
Size Of Derived:
"
<<
sizeof
(Derived)
<<
endl;
//
父类型指针指向子类型对象数组
Base
*
pBase
=
new
Derived[CLASS_NUM];
int
i
=
0
;
while
(i
<
CLASS_NUM)
{
//
按父类型大小裁剪连续分布的子类型对象数组空间
pBase[i].TestNonVirtual();
++
i;
}
TestArray(pBase);
delete []pBase;
return
0
;
}
catch
(exception
&
e)
{
cout
<<
e.what()
<<
endl;
}
输出:
Size Of Base: 8
Size Of Derived: 16
Base::NonVirtual:1
Base::NonVirtual:10
Base::NonVirtual:2
Base::NonVirtual:20
Base::NonVirtual:3
Base::NonVirtual:1
Base::NonVirtual:10
Base::NonVirtual:2
Base::NonVirtual:20
Base::NonVirtual:3
*********************************
连续5个Derived对象大小为16*5的空间,被当作5个Base的大小8*5来切割,
所以,每个Derived对象被解析成为两个Base对象,切割后的第二个Base实际上还是在第一个Derived里面,
第一个Derived的前8个字节是父类Base,后8个字节是lDerived和iDerived,其中iDerived被解析成为第2个Base的iBase,
因为调用的是非虚函数,所以直接调用Base::TestNonVirtual(),但取到的iBase的值确是第一个Derived的iDerived。
虚函数的情况:
int
i
=
0
;
while
(i
<
CLASS_NUM)
{
//
按父类型大小裁剪连续分布的子类型对象数组空间
pBase[i].TestVirtual();
++
i;
}
输出:
Size Of Base: 8
Size Of Derived: 16
Derived::Virtual:1
程序崩溃!
因为是虚函数,所以首先根据对象的vPointer找到虚函数表中对应的函数,再调用,
本来Base的虚函数表中应该对应的是Base的TestVirtual,
但这里将第一个Derived的前两个字节解析成了Base,
所以第一个Derived的vPointer被当作了Base的vPointer,
然后从虚函数表中找到对应的子类所override的函数,并输出iBase,
接着将第一个Derived对象的第3个字节被错误地解析成为第2个Base的vPointer,
调用函数时,程序崩溃。
posted on 2009-05-14 21:40
大胖
阅读(353)
评论(0)
编辑
收藏
引用
只有注册用户
登录
后才能发表评论。
【推荐】100%开源!大型工业跨平台软件C++源码提供,建模,组态!
网站导航:
博客园
IT新闻
BlogJava
知识库
博问
管理
Powered by:
C++博客
Copyright © 大胖