鱼C论坛

 找回密码
 立即注册
查看: 992|回复: 17

[已解决]C++编程中代码运行结果的疑问!谁能帮忙解释一下!!

[复制链接]
发表于 2020-6-29 10:03:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 jhanker 于 2020-6-29 11:20 编辑

在学习C++过程中,对于子类,父类在运行时出现的结果和自己的认为的结果有差别,望大家帮忙解释一下
由于没有权限上传图片,只能让大家自己复制运行代码了!
#include <iostream>
using namespace std;
class A//有虚函数的基类A
{
public:
A() { m_a='A'; }
virtual void fun() { cout<<"A::fun() and m_a="<<m_a<<endl; }
protected:
char m_a;
};

class C//无虚函数的基类C
{public:
C() { m_c='C'; }
void fun() { cout<<"C::fun() and m_c="<<m_c<<endl; }
protected:
char m_c;
};

class B : public A
{
public:
B() { m_a='B'; }
void fun() { cout<<"B::fun() and m_a="<<m_a<<endl; }
void b_fun() { cout<<"B::b_fun"<<endl; }
private:
char m_b;
};

class D : public C
{
public:
D() { m_c='D'; }
void fun() { cout<<"D::fun() and m_c="<<m_c<<endl; } void d_fun() { cout<<"D::d_fun"<<endl; }
private:
char m_d;
};

int main()
{
A * a = new A;
B * pb;
pb = static_cast<B *>(a);
pb->fun();
pb->b_fun();
C * c = new C;
D * pd;
pd = static_cast<D *>(c);
pd->fun();
pd->d_fun();
A * pa = new B; pa->fun(); //pa->b_fun();
C * pc = new D; pc->fun(); //pc->d_fun();
return 0;
}
最佳答案
2020-6-29 10:16:30
jhanker 发表于 2020-6-29 10:11
运行的结果 感觉是错乱的,但还是能运行

我没发现什么问题,还有你的代码格式烂的我头疼。

你真的不是新手?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2020-6-29 10:09:36 | 显示全部楼层
你想问什么啊?说明白
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-29 10:09:45 | 显示全部楼层
感觉编译器错乱了都
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-29 10:11:06 | 显示全部楼层

运行的结果 感觉是错乱的,但还是能运行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-29 10:16:30 | 显示全部楼层    本楼为最佳答案   
jhanker 发表于 2020-6-29 10:11
运行的结果 感觉是错乱的,但还是能运行

我没发现什么问题,还有你的代码格式烂的我头疼。

你真的不是新手?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-29 10:17:27 | 显示全部楼层

   
  A * a = new A;
        B * pb;
        pb = static_cast<B *>(a);
        pb->fun();
        pb->b_fun();
上面的代码pb是指向 A的实例的,运行pb->fun();结果是运行A实例的函数 这可以理解,但按道理pb->b_fun();应该无法运行才对啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-29 10:21:02 | 显示全部楼层
永恒的蓝色梦想 发表于 2020-6-29 10:16
我没发现什么问题,还有你的代码格式烂的我头疼。

你真的不是新手?

我算是个新手吧,我大学不是学计算机的,上面的代码不是我写的,是其他人问我,我感觉不太好解释,所以希望这里的高手能解释解释
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-29 10:26:00 | 显示全部楼层
jhanker 发表于 2020-6-29 10:17
上面的代码pb是指向 A的实例的,运行pb->fun();结果是运行A实例的函数 这可以理解,但按道理pb-> ...

咱把代码整理整理再发上来呗,看得我头痛
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-29 10:36:53 | 显示全部楼层
本帖最后由 jhanker 于 2020-6-29 10:51 编辑

我觉得这代码主要是为了了解在类继承过程中要注意指针的使用,如果使用不当会出现内存泄露,编写代码的老师估计是个高手,是为了让学生理解c++的底层机理吧,我把代码改了一点,你们可以运行看看!
#include <iostream>
using namespace std;
class A//有虚函数的基类A
{
public:
        A() { m_a='A'; }
        virtual void fun() { cout<<"A::fun() and m_a="<<m_a<<endl; }
protected:
        char m_a;
};

class C//无虚函数的基类C
{public:
C() { m_c='C'; }
void fun() { cout<<"C::fun() and m_c="<<m_c<<endl; }
protected:
        char m_c;
};

class B : public A
{
public:
        B() { m_a='B'; m_b='B';}
        void fun() { cout<<"B::fun() and m_a="<<m_a<<endl; }
        void b_fun() { cout<<"B::b_fun() and m_a="<<m_a<<" and m_b="<<m_b<<endl; }
private:
        char m_b;
};

class D : public C
{
public:
        D() { m_c='D'; m_d='D';}
        void fun() { cout<<"D::fun() and m_c="<<m_c<<endl; }
        void d_fun() { cout<<"D::d_fun() and m_c="<<m_c<<" and m_d="<<m_d<<endl; }
private:
        char m_d;
};

int main()
{
        A * a = new A;
        B * pb;
        pb = static_cast<B *>(a);
        pb->fun();
        pb->b_fun();
        C * c = new C;
        D * pd;
        pd = static_cast<D *>(c);
        pd->fun();
        pd->d_fun();
        A * pa = new B; pa->fun(); //pa->b_fun();
        C * pc = new D; pc->fun(); //pc->d_fun();
        return 0;
}
例如当运行pb->b_fun();的时候其实已经出现内存泄露了,m_b的值根本就不存在,但B::b_fun()函数照样被调用了
其实老教授是想让他的学生明白虚函数表。
虚成员函数的处理方法,在VC++ 中,与虚继承的处理方式如出一辙,这样同样也造成对象实例占用了更多内存空间,因为实例需增加一个隐藏的“虚函数表指针”(virtual function pointer 或 virtual function table pointer)成员变量,简称vfptr,从而达C++的多态目的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-29 10:56:26 | 显示全部楼层
永恒的蓝色梦想 发表于 2020-6-29 10:16
我没发现什么问题,还有你的代码格式烂的我头疼。

你真的不是新手?

我在电脑上 看代码格式还是挺清楚的 没有出现混行现象
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-29 10:57:35 | 显示全部楼层
jhanker 发表于 2020-6-29 10:56
我在电脑上 看代码格式还是挺清楚的 没有出现混行现象

什么混行
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-29 11:01:51 | 显示全部楼层

我是说我在电脑显示器上看,没有出现几行代码显示在同一行的情况,不知道手机端,会不会因为显示界面小,出现几行代码混乱的显示在一起的情况
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-29 11:09:04 | 显示全部楼层
本帖最后由 jhanker 于 2020-6-29 11:11 编辑


其实这段让人头晕的代码对提高C++编译器的认知有好处。
分析时需要搞清楚:调用函数的指针变量类型是什么?指针指向的实例是谁?指向的实例的类型是什么?运行时调用的函数是哪个类成员函数?显示的成员变量堆内存区是否开辟了空间?
由于我感觉要讲清楚前面问题需要太多的知识,不知道有没有简单一些的讲法,所以才把问题抛给你们,想获得一个简单一点的解释。不好意思,麻烦你们了!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-6-29 12:14:27 | 显示全部楼层
jhanker 发表于 2020-6-29 11:01
我是说我在电脑显示器上看,没有出现几行代码显示在同一行的情况,不知道手机端,会不会因为显示界面小, ...

我说你的代码风格烂
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-29 12:29:47 From FishC Mobile | 显示全部楼层
本帖最后由 jhanker 于 2020-6-29 12:31 编辑

怎么刚才手机打的内容一发布就空了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-29 12:40:32 | 显示全部楼层

我知道这样的代码风格不好,也知道在开发大型程序的时候代码风格很重要。但我也不是科班出身,没有系统学过,还真希望你能贴一个你觉得代码风格好的短一点的代码让我学习学习。我其实对怎么样的风格算好现在也不太知道!希望能改变改变我的认识
我声明一下上面的代码不是我写的哦
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-6-30 09:54:47 | 显示全部楼层
代码风格确实比较烂!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2020-7-1 08:48:41 | 显示全部楼层
jhanker 发表于 2020-6-30 09:54
代码风格确实比较烂!

下载个 VS,VSCODE,CLION 格式化一下就好了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-6-15 10:00

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表