C++ 疑难杂症求解

来源:百度知道 编辑:UC知道 时间:2024/06/11 15:36:56
#include <iostream.h>
#include <string>
using namespace std;
class s1{
public:
virtual void print(){
cout<<"s1::print"<<endl;
}
};

class s2 : public s1{
public:
void print(){
cout<<"s2::print"<<endl;
}
};

void print(s1 s){
s.print();
}
int main(void){
s2 b;
print(b);//输出是s1::print

return 0;
}

我还增加了成员函数的试验,在void print(s1 s)中调用完全都是基类的,请高手解惑。
是子类对象中为什么没有覆盖掉基类的print呢?
1楼的朋友能不能直接解释一下这个现象的原因,我没用基类指针指向子类对象,不是多态的问题。
其实我想知道是对象的内存布局导致的,还是在函数传参时某些原因导致的!

谢谢2楼3楼的的朋友,如果讲讲这个类型转换的过程,,一般子类转成父类时是如何实现,哪些数据会保留,哪些数据会丢失,哪些数据会更改,为什么这样的转换可以实现呢?
它的内存布局是如何保证这样的转换可以成功呢????
在下感激涕零!

warmwormn同学说的有问题,我正好试验过把s2中的print变成虚函数去让虚表修改,但调用的仍然是s1::print,这也正是我很不解的另一个问题

可能是我问的不清楚,
lin1270说的正是我想要的,但这个转换不只是切割吧,比如虚函数表如果不作相应的修改还是不行吧?

最后一个问题,怎

我也来说一下。
这个原因是对象切割导致的。

首先说一下对象包含。我们知道,大多数编译器的原理是认为,子类包含基类。
所以s2中有一个s1。

void print(s1 s),当传递一个s2的对象时,因为s2不是s1,会进行类型转换,如果向上转换是默认的,一般都会成功。但是基类中不含有s2中私有的东西。所以在进行转换的时候,是不会把子类中私有的东西转换为基类中的东西的。
那么在进行转换的时候,会把子类中属于基类的东西复制到临时对象中,然后才赋函数进行运算。

这就发生了对象切割,即把子类中自己的东西去除,而保存基类固有的。这是C++继承中要避免的问题。很多高级读本都有这个东西的介绍。

所以实际上传递给函数的是一个基类的对象,而不是一个子类对象。输出的就是基类的成员函数。

一般这种都会传递一个引用或指针,以免出现对象切割。

啊啊啊啊啊啊
弄错了弄错了,呵呵呵

虚调用都是要用指针或者引用的,哈哈哈
void print(s1 s)是一个隐式的类复制
系统会根据s1的内存分布 复制到s变量中
所以....

----------------------------

类的虚函数,会让类产生一个虚函数表,以表明某个函数的入口地址
如s1中有一个虚函数表,表里有一个print函数的入口

子类中如果有相同的虚函数,则系统在编译时,修改父类中虚函数表中
该函数的入口地址
如s2中声明函数为virtual void print,则在本类的虚函数表中原来父类的
虚函数s1::print入口被改为s2::print,这样用父类函数指针就可以调用
子类中的虚函数

由于s2中你定义的是void print,是个实函数,所以虚函数表没有被修改
在void print(s1 s)函数中,将会调用s1::print

------------
以上

看一下这两个例子,或许你就明白了