请教关于基类和继承的问题

ljseven 2004-01-02 09:59:50
有如下程序
class CBase
{
public:
virtual void printf()
{
cout<<"CBase::printf()"<<endl;
cc();
}
};
class CDerived : public CBase
{
public:
virtual void printf()
{
cout<<"CDerived::printf()"<<endl;
}
void Addition(void)
{
cout<<"CDerived::Addition()"<<endl;
}
} ;
void main()
{
CBass a;
CDerived* b;
b=(CDerived*)&a;
b->Addition();
}
此程序运行会出现CDerived::Addition()
b只是它的地址指向a的内存地址,而a的内存地址中根本没有Addition,为何b->Addition()不会出现不可预料的错误,此时b的内存构造是什么样的?
...全文
74 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
fohoo 2004-01-07
  • 打赏
  • 举报
回复
同意smilewang(急速传说)

main返回的时候非法操作,是因为把main的返回地址覆盖了

在main中加一个int变量就不会了
vocanicy 2004-01-02
  • 打赏
  • 举报
回复
成员函数带有对象指针参数的函数
可以理解为
Addition(CDerived* this, param a, param b,...)
实际上
你的b->Addition,就是将 &a转换为CDerived*类型指针传递给函数,
ljseven 2004-01-02
  • 打赏
  • 举报
回复
我想了2天了,各位帮帮我啊
ljseven 2004-01-02
  • 打赏
  • 举报
回复
to ismezy2002(口水大军) :
小弟对c++类的内存构造始终是一知半解,这次看了些资料想加深理解
ljseven 2004-01-02
  • 打赏
  • 举报
回复
to Semigod:
如果我在CDerived 的Addition中访问CBase的成员变量 假设为int m_base;
程序也不会出错,因为在a的内存中m_base 已经存在,下面是我又一个实验,结果是通过
class CBase
{
public:
int m_base;
virtual void printf()
{
cout<<"CBase::printf()"<<endl;
}
};
class CDerived : public CBase
{
public:
int m_derived;
virtual void printf()
{
cout<<"CDerived::printf()"<<endl;
}
void Addition(void)
{
cout<<"CDerived::Addition()"<<endl;
m_base=1;
m_derived=1;
}
} ;
void main()
{
CBass a;
CDerived* b;
b=(CDerived*)&a;
b->Addition();
}
ismezy2002 2004-01-02
  • 打赏
  • 举报
回复
研究的这么深?不过好像没有谁像你这么用的吧,记得C++教程说过这种用法是不允许的
Semigod 2004-01-02
  • 打赏
  • 举报
回复
如果你懂汇编的话,这个问题就很容易理解

CBass a; 这一句申请了一个CBass对象,在内存中,这个对象是一块内存区,存储了CBass的所有成员变量。
CDerived * b是一个指向对象的指针,也就是指向对象所占内存区的指针,
b=(CDerived*)&a; 一句正是将 CBass a;一句得到的指针给了b


b->Addition();调用 Addition() 没有出错的原因是,你的Addition()没有访问任何a的成员变量。
汇编上只是将a的指针放到ecx寄存器,然后调用Addition(),而在Addition()中根本就没
有使用ecx寄存器中的值
ljseven 2004-01-02
  • 打赏
  • 举报
回复
但是为何在执行Addition()的时候不出现非法操作而是出现在main返回的时候呢?
ljseven 2004-01-02
  • 打赏
  • 举报
回复
是的,指针是过界了,我在程序开头定义了一个 CDerived c,而这里没有写出来,当去掉
定义C就发现会非法操作,原因是成员m_drived把main函数的返回值覆盖,并被改为m_drived了,。
smilewang 2004-01-02
  • 打赏
  • 举报
回复
指针写过界了而已!
=====================
以vc6.0 编译器 为例: 看看下面程序的运行结果

// cplustest.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <conio.h>


using namespace std;

class CBase
{
public:
virtual void printf()
{
cout<<"CBase::printf()"<<endl;

}
};

class CDerived : public CBase
{
public:
int m_drived;
virtual void printf()
{
cout<<"CDerived::printf()"<<endl;
}
void Addition(void)
{
cout<<"CDerived::Addition()"<<endl;

m_drived = 12;
}
} ;


int main(int argc, char* argv[])
{


int nTest = 0; //<< look here
CBase a;


CDerived* b;
b=(CDerived*)&a;

b->Addition();

cout<< nTest << endl; //<< look here

getch();

return 0;
}

结果为12

nTest 的值本来为0,但是因为 在阿Addition()函数中,指针越界,导致nTest的值被修改。
sharkhuang 2004-01-02
  • 打赏
  • 举报
回复
真的可以吗?
8412230 2004-01-02
  • 打赏
  • 举报
回复
哦,是嘛?没有这么用过,按道理来说应该是不行的!!回去查查资料看看再说!
ljseven 2004-01-02
  • 打赏
  • 举报
回复
to carolbaby(猫儿)
不会我还在后面加了
class CDerived : public CBase
{
public:
int m_derived;
void Addition(void)
{
cout<<"CDerived::Addition()"<<endl;
m_base=1;
m_derived=1;
cout<<"m_derived="<<m_derived<<endl;
}
} ;
程序依然可以正确的运行!!!!
carolbaby 2004-01-02
  • 打赏
  • 举报
回复
class CDerived : public CBase
{
public:
int m_derived;
void Addition(void)
{
cout<<"CDerived::Addition()"<<endl;
m_base=1;
m_derived=1;
}
} ;

访问了m_derived 还会不出错吗?
ljseven 2004-01-02
  • 打赏
  • 举报
回复
to vocanicy(刺客)
a的内存中没有CDerived 的成员变量啊,难到转换过程中能够自动的把CBase的内存块转换为CDerived的内存块吗?
upuper 2004-01-02
  • 打赏
  • 举报
回复
up

16,551

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Creator Browser
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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