为什么会发生切割?

widewave 2002-09-09 01:57:59
// test.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

class a
{
};

class b : public a
{
};

class c : public a
{
};

int GetType(a & A)
{
return 0;
}

int GetType(b & B)
{
return 1;
}

int GetType(c & C)
{
return 2;
}

int main(int argc, char* argv[])
{
printf("Hello World!\n");
a A;
printf("%d\n", GetType(A));
b B;
printf("%d\n", GetType(B));
c C;
printf("%d\n", GetType(C));
a *pA = &C;
printf("%d\n", GetType(*pA));
return 0;
}


运行结果是:
Hello World!
0
1
2
0

问题:为什么GetType(*pA) 得到0?难道发生切割了吗?为什么这样?
...全文
55 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
widewave 2002-09-22
  • 打赏
  • 举报
回复
我刚刚看了《设计模式》。
Visitor虽然能添加新的虚函数,但是如果原有的类并不是Visitor模式的话,Visitor也无能为力。
看来我再研究一下COM再说吧。

To:yonk(一无所有)
我无法改变类a, b, c的设计。
yonk 2002-09-11
  • 打赏
  • 举报
回复
作为类的 成员函数
yonk 2002-09-11
  • 打赏
  • 举报
回复
inside the c++ object model
中曾经比较详细的讲解了 关于继承的一个问题。
我认为这个问题应该归结到 继承 中内存的分配上。
c继承自A, 因而 在内存上 应该是 c的内存前面部分是A类型的,后面才是
继承后c特有的。
::(我自己也看不懂在说些什么了。你看看书吧:)

也就是说那个问题不是 用不用 虚函数的问题。
而是类型的问题。

建议改用 虚函数来解决。
dsangvei 2002-09-11
  • 打赏
  • 举报
回复
gz
widewave 2002-09-11
  • 打赏
  • 举报
回复
TO:fangrk(加把油,伙计!)
首先谢谢您的热心。
你的例子挺清楚的。不过好象必须要修改类a, b, c的设计。可惜,那些类不是由我来维护的。

看来只好使用PNP了,不知道PNP有什么限制?
回头我好好看看《设计模式》再说吧。
fangrk 2002-09-11
  • 打赏
  • 举报
回复
我自己尝试了一下,改为虚拟,但是编译都无法通过。应该是我的理解还不够。以我现在的理解,一般虚拟函数不是这样使用的,譬如,要判断一个参数究竟是什么,我下面这个例子可以解决疑问:
#include <iostream>
using namespace std;
class a
{
public:
void virtual say() const {cout<<"I am a"<<endl;}
};

class b : public a
{
public:
void virtual say() const {cout<<"I am b"<<endl;}
};

void SaySome(const a & A)
{
A.say();
}

int main(int argc, char* argv[])
{
a A;
b B;
SaySome(A);
SaySome(B);
a *p=new b;
SaySome(*p);
delete p;
return 0;
}
答案:
I am a
I am b
I am b
lanfengjiyue 2002-09-11
  • 打赏
  • 举报
回复
可以看看这个帖子:
http://www.csdn.net/expert/topic/1014/1014885.xml?temp=.275799
widewave 2002-09-11
  • 打赏
  • 举报
回复
同意:fangrk(加把油,伙计!) 和kenryHuang(冷的时候我想死) 。

我也意识到了错误所在。

但是,我必须根据类型不同,得到不同的值。如果我知道它的类型,我当然可以直接调用GetType(c &C);不过现在我只知道参数类型是a, b, c其中之一。同时,这些类不是由我来维护,我不能给它们添加新的虚拟函数。如果要使用swicth...case又显得有点儿丑陋。cast太多也挺烦的。

请问大虾,有没有好的解决方法?
谢谢。
ice1010 2002-09-11
  • 打赏
  • 举报
回复
因为你把pA生明成a*,当然调用的是a中的GETTYPE(),
如果你把GETTYPE()声明成VIRTUAL,那编译起才在运行时
动态的确定调用哪个函数,这就是多态.
widewave 2002-09-11
  • 打赏
  • 举报
回复
同意:fangrk(加把油,伙计!) 和kenryHuang(冷的时候我想死) 。

我也意识到了错误所在。

但是,我必须根据类型不同,得到不同的值。如果我知道它的类型,我当然可以直接调用GetType(c &C);不过现在我只知道参数类型是a, b, c其中之一。同时,这些类不是由我来维护,我不能给它们添加新的虚拟函数。如果要使用swicth...case又显得有点儿丑陋。cast太多也挺烦的。

请问大虾,有没有好的解决方法?
谢谢。
blh 2002-09-11
  • 打赏
  • 举报
回复
GetType(*pA)调用GetType(a &A)
*pA不是c类型而是a
kenryHuang 2002-09-11
  • 打赏
  • 举报
回复
很明显,你的问题是函数重载,而不是多态。
你的函数调用在编译时期就绑定了。
根据函数重载的绑定规则
GetType(a &A)是最佳匹配。
因为*pA的类型是a.

你要调用GetType(c& C)的方法是把*pA强制转型为C

C* pC = static_cast<C *>(pA);
GetType(*pC);
fangrk 2002-09-11
  • 打赏
  • 举报
回复
a *pA = &C;
printf("%d\n", GetType(*pA));
为何调用GetType(A & a)?
因为没有采用virtual机制,所以在编译的时候就决定了类型是a(指针源头 a*pA)
widewave 2002-09-11
  • 打赏
  • 举报
回复
不好意思,我把函数重载和多态性搞混了。不过,我确实需要多态性。然而,a, b, c类都不是由我来维护的,应该怎么办呢?
widewave 2002-09-09
  • 打赏
  • 举报
回复
to:boxban(master-dreamer)

a *pA = &C;
printf("%d\n", GetType(*pA));

(*pA)是C类型的。所以,决议的结果应该调用
int GetType(c & C);
才对啊。
不知道为什么?

to:garfield_82(我真笨,真的)

因为GetType函数的参数是引用,并没有发生从派生类向基类的转换啊。

唉,难道编译器没有使用动态绑定吗?怎么样强制它动态绑定呢?加一个PNP的虚类可以吗?困惑中......
sjf331 2002-09-09
  • 打赏
  • 举报
回复
调用函数参数类型不对。
garfield_82 2002-09-09
  • 打赏
  • 举报
回复
从派生类向基类转换时,会发生切割。原因是由于派生类对象的大小与基类对象的大小不一致而导致的。
boxban 2002-09-09
  • 打赏
  • 举报
回复
这与切割没有关系,因为你传入的参数是a类型,所以显示的调用了int GetType(a & A)
striking 2002-09-09
  • 打赏
  • 举报
回复
printf("%d\n", GetType(*pA));
调用的是GetType(a & A);

69,371

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧