Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 无法在C+;中调用派生类函数+;_C++ - Fatal编程技术网

C++ 无法在C+;中调用派生类函数+;

C++ 无法在C+;中调用派生类函数+;,c++,C++,我肯定我漏掉了部分密码 我有以下代码: #include <iostream> using namespace std; class Record { private: int age; string name; public: virtual int getType()=0; }; class Student: public Record { private: int level_; public: Student()

我肯定我漏掉了部分密码

我有以下代码:

#include <iostream>

using namespace std;

class Record
{
private:
    int age;
    string name;
public:
    virtual int getType()=0;
};


class Student:  public Record
{
  private:
     int level_;
  public:
     Student()
     {
        level_=1;
     };
     ~Student() {};
     int getType()
     {
        return 1;
     }

     int level()
     {
        return level_;
     }
};


int main (int argc, char ** argv)
{
  Record *r = new Student();
  cout <<"tuype " << r->getType();
  cout <<"Class " << r->level();
}
#包括
使用名称空间std;
课堂记录
{
私人:
智力年龄;
字符串名;
公众:
虚拟int getType()=0;
};
班级学生:公开记录
{
私人:
国际水平!;
公众:
学生()
{
级别=1;
};
~Student(){};
int getType()
{
返回1;
}
整数级()
{
返回水平;
}
};
int main(int argc,字符**argv)
{
记录*r=新学生();

cout记录中缺少virtual method level()声明。另外,为了防止资源泄漏,您需要在记录中定义虚拟析构函数

class Record
{
...
public:
  virtual ~Record() {}
  virtual int level() = 0;
  virtual int getType() = 0;
};

更改记录以进行
level()
virtual

你写道:

Record *r = new Student();
在这一行之后,编译器将
r
视为指向
记录
或某个
记录
派生类(它是派生类)的指针,但它只知道为
记录
指定的接口。没有
虚拟
级别()
记录
中的
功能,因此您无法通过
记录
界面访问
学生
的级别功能。只需将此功能添加到
记录
,您就可以:

virtual int level() { return 0; }  // Student may override implementation

另一种选择:检查记录*是否针对学生

我上面说

Record
中没有
virtual
level()
函数,因此您无法通过
Record
界面访问
学生的level函数

…并显示如何添加到
记录
界面,但另一种方法是再次访问
学生
界面,如中所示:

if (Student* p = dynamic_cast<Student*>(r))
    std::cout << "Level " << p->level() << '\n';
这确保在使用基类指针(例如,如果在
main()
的底部添加
delete r;
)删除派生对象时调用派生类的析构函数实现(编译器仍将确保随后调用基类析构函数)

如果不这样做,这是未定义的行为,并且充其量您会发现在派生类中添加的任何其他数据成员都没有调用它们的数据成员…对于无害的
int
,但是对于
std::string
,它可能会泄漏内存,甚至会持有锁,导致程序稍后挂起。当然,这不是一个好方法依赖于最佳情况下未定义的行为的想法;-)但我认为了解什么绝对不会发生是有用的,除非您将基本析构函数
设置为虚拟的

建议对学生进行一些小的改进

如果您在
记录
中使
级别
虚拟
,那么为了让
学生
类的读者更清楚地知道
级别()
是从基类实现的
虚拟
函数,如果您有一个具有适当C++11能力的编译器,您可以使用
覆盖
关键字:

int level() override
{
    return level_;
}

如果在基类中找不到匹配的(non-
const
virtual int level()
,这将导致编译器错误,因此它可以避免一些偶然的故障排除。如果您觉得
virtual
关键字有文档价值,也可以重复该关键字(对于C++03特别好,其中
覆盖
不是一个选项),但它不会造成任何功能上的差异-函数保持
虚拟
,只要它是(隐式或显式的)从基类重写虚函数。

因为
记录
类对名为
level()的函数一无所知。


您需要在基类中创建一个虚拟的
level()
函数。

在基类中创建虚拟函数,如

virtual int level() = 0;

一旦您在基类记录中创建了虚拟函数
level()
,学生就必须在学生类中拥有它的函数
level()
。目前您在类记录中没有虚拟
level()
函数,因此您无法访问学生类的
level()
函数当前正在使用基类记录。

编译时,应收到类似以下内容的错误消息:

error C2039: 'level' : is not a member of 'Record'
您需要在Record类中添加以下内容:

virtual int level()=0;

您无法调用
r->level()
,因为您试图调用一个类记录中不存在的函数。在您的特定情况下,
r
指向的数据不仅是
Record
,同时也是
学生,因此您可以选择:

Student *r = new Student();
cout <<"tuype " << r->getType();
cout <<"Class " << r->level()

另一个问题:您应该将
Record
类中的析构函数标记为virtual,因为当您
删除r
时,
学生的构造函数将不会被调用学生实例通过以下方式被升级为Record:

Record *r = new Student();
在保存一个学生实例时,r代表记录。r->getType()函数调用使用C++的多态机制绑定到Student::getType。 要调用level()函数,可以:

1. Add a virtual function level() to Record class. 2. downcasting r to Student class, as follows: 1.向Record类添加虚拟函数级别()。 2.将r向下播送至学生班级,如下所示:
Student*r\u new=dynamic\u cast(r);
r_new->level();

你的
Record
类应该有一个虚拟析构函数。你的
Student
类应该有一个隐式定义的析构函数。并且你的函数都不需要在主体后加分号。我认为通常使用方法
getType()不是一个好主意
。这并不总是一件坏事,但如果可能的话,请尽量避免。不要忘记为继承设计的类中的虚拟析构函数,它非常有用important@chris:+1,用于虚拟析构函数建议,但无论
Student
是否有隐式定义的析构函数,分号,shiver;-).@TonyD,不在这里,但是当你进入有影响的领域时,把一个放在自己身上只会给你带来劣势。@chris:cou
Record *r = new Student();
cout <<"tuype " << r->getType();
cout <<"Class " << dynamic_cast<Student*>(r)->level()
class Record { ...
   virtual int level() = 0;
}
Record *r = new Student();
1. Add a virtual function level() to Record class. 2. downcasting r to Student class, as follows:
Student *r_new = dynamic_cast<Student>(r); 
r_new->level();