首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

[]关于指针调用虚函数的有关问题

2012-02-29 
[求助]关于指针调用虚函数的问题今天在学习c++的继承与虚函数这块,在做一个练习的时候遇到了如下问题:设有

[求助]关于指针调用虚函数的问题
今天在学习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.增大数组长度,并在构造函数中加上安全判定

热点排行