[求助]关于指针调用虚函数的问题
今天在学习c++的继承与虚函数这块,在做一个练习的时候遇到了如下问题:
设有基类Cd,派生类classic,两个类中都有显示成员变量的虚函数Report(),并且产生两个对象 c1和c2,其中c1是基类类型,c2是派生类类型,然后分别采用对象直接调用Report()函数,指针、引用调用Report()函数。直接调用的时候,两者都没有问题。但是首先定义一个基类指针Cd *pcd=&c1,然后使用语句 pcd->Report(),则出现内存错误。如果令 pcd=&cd2 ; pcd->Report(); 则派生类显示正常。同样,采用引用调用,如下函数void Bravo(Cd &disk)
{
disk.Report();
}
若使用的是c1引用则会出错,若使用c2引用则正确。
以下是程序代码,可能问题并不是很难,是我经验不够或者有部分低级错误,但还希望谢谢各位不吝赐教,再次感谢各位热心朋友。
//cd.h
#ifndef CD_H_
#define CD_H_
class Cd
{
private:
char performers[50];
char label[20];
int selections;
double playtime;
public:
Cd(char *,char *,int ,double );
Cd(const Cd &);
Cd();
virtual ~Cd();
virtual void Report() const;
Cd & operator= (const Cd &);
};
class classic:public Cd
{
private:
char cdinfo[30];
public:
classic(char *,char * ,char *, int ,double);
classic(char *,const Cd &);
classic();
virtual ~classic();
virtual void Report() const;
classic & operator= (const classic &);
};
#endif
//cd.cpp
#include <iostream>
#include "cd.h"
using std::cout;
using std::endl;
Cd::Cd(char *s1,char *s2,int n,double x)
{
strcpy(performers,s1);
strcpy(label,s2);
selections=n;
playtime=x;
}
Cd::Cd(const Cd & c)
{
strcpy(performers,c.performers);
strcpy(label,c.label);
selections=c.selections;
playtime=c.playtime;
}
Cd::Cd()
{
strcpy(performers,"None");
strcpy(label,"None");
selections=0;
playtime=0;
}
Cd::~Cd()
{
cout<<"Cd destructor called!\n";
}
void Cd::Report() const
{
cout<<"performers : "<<performers<<endl;
cout<<"label : "<<label<<endl;
cout<<"selecions : "<<selections<<endl;
cout<<"playtime : "<<playtime<<endl;
}
Cd & Cd::operator =(const Cd & c)
{
if(this==&c)
return *this;
strcpy(performers,c.performers);
strcpy(label,c.label);
selections=c.selections;
playtime=c.playtime;
return *this;
}
classic::classic(char *info,char *p,char *l, int s,double t):Cd(p,l,s,t)
{
strcpy(cdinfo,info);
}
classic::classic(char *info,const Cd & c):Cd(c)
{
strcpy(cdinfo,info);
}
classic::classic():Cd()
{
strcpy(cdinfo,"None");
}
classic::~classic()
{
cout<<"classic destructor called!\n";
}
void classic::Report() const
{
cout<<"Classic CD information : "
<<cdinfo<<endl;
Cd::Report();
}
classic & classic::operator = (const classic & c)
{
if(this==& c)
return *this;
Cd::operator =(c);
strcpy(this->cdinfo,c.cdinfo);
return *this;
}
//usecd.cpp
#include<iostream>
#include "cd.h"
using namespace std;
void Bravo(const Cd & disk);
int main()
{
Cd c1("Beatles","Capitol",14,35.5);
classic c2=classic("Piano Sonata in B flat, Fantasia in C",
"Alfred Brendel","Philips",2,57.17);
cout<<"Using object directly: \n";
cout<<"-----------------------------\n";
c1.Report();
cout<<"-----------------------------\n";
c2.Report();
cout<<"-----------------------------\n"; //直接调用,显示正常;
cout<<"Using type cd * pointer to objects: \n";
Cd *pcd = & c1;
pcd->Report(); //此处则产生错误;
pcd = & c2;
pcd->Report();
cout<<"-----------------------------\n";
cout<<"Calling a function with a Cd reference argument: \n";
Bravo(c1); //此处也会产生错误,估计原因和指针调用时错误相同?
cout<<"-----------------------------\n";
Bravo(c2);
cout<<"-----------------------------\n";
cout<<"Testing assignment : \n";
classic copy;
copy=c2;
copy.Report();
cout<<"-----------------------------\n";
return 0;
}
void Bravo(const Cd & disk)
{
disk.Report();
}
[解决办法]
classic c2=classic("Piano Sonata in B flat, Fantasia in C",
"Alfred Brendel","Philips",2,57.17);
这里的字符串过长,越界了
[解决办法]
程序本身没有错误,但在调用classic的构造函数时发生内存溢出,会造成一些不可预料的结果,在程序结束时也会产生运行时错误。
具体如下:classic的成员变量char cdinfo[30]为30个字符,而在main函数中 classic c2=classic("Piano Sonata in B flat, Fantasia in C",
"Alfred Brendel","Philips",2,57.17); cdinfo被初始化的值超过30个字符,会造成内存溢出,进而产生意外的结果。另外两个成员变量performers和label存在相同隐患。
解决方案有两种:1.直接使用指针
2.增大数组长度,并在构造函数中加上安全判定