简体   繁体   English

虚函数和派生类

[英]virtual function and derived class

Let me show you the simple C++ code example first. 让我首先向您展示简单的C ++代码示例。

#include <iostream> 
using namespace std;

class Person{

  string m_name;
public:
  virtual void saySomething(){
    cout << "I am a person.";
  }
};

class Student:public Person{
public:

  void saySomething(){
    cout << "I am a student." << endl;
  }
};

class CSStudent:public Student{
public:

  void saySomething(){
    cout << "I am a CS Student." << endl;
  }
};

int main(){
  Person* p = new Person();
  Student* s = new Student();
  CSStudent* c = new CSStudent();

  ((Student*)c)->saySomething();

  return 0;
}

In my example, Student is a derived class of Person. 在我的示例中,Student是Person的派生类。 Also, CSStudent is a derived class of Student. 另外,CSStudent是Student的派生类。 I know virtual keyword make it possible to determine if it is derived class. 我知道虚拟关键字可以确定它是否是派生类。

Question 1. 问题1

((Student*)c)->saySomething(); ((学生*)c)-> saySomething();

Why do I get "I am a CS Student."? 为什么会收到“我是一名CS学生”? I expected "I am a Student." 我期望“我是学生”。 since I specify virtual keyword only for the Person. 因为我只为Person指定了虚拟关键字。

Question 2. 问题2。

I saw an example that puts a virtual keyword to only base case. 我看到了一个将虚拟关键字仅置于基本情况下的示例。 Also, I saw an example that puts virtual keywords to all base case and derived classes. 另外,我看到了一个将虚拟关键字应用于所有基本案例和派生类的示例。 What's the difference between these two? 两者有什么区别?

Question 3. 问题3。

virtual function is determined in run time. 虚拟功能是在运行时确定的。 What about non-virtual function? 非虚拟功能呢? Is it determined in compile time? 是在编译时确定的吗?

For the first question, even if you cast c to another class based on the same base-class, it's still the original class (ie CSStudent ). 对于第一个问题,即使将c CSStudent基于同一基类的另一个类,它仍然是原始类(即CSStudent )。 Virtual functions are (almost always) implemented through a jump table. 虚函数(几乎总是)是通过跳转表实现的。 So the c object have a table which contains the address to the actual function in the c object. 因此, c对象具有一个表,其中包含c对象中实际函数的地址。 This table will not change because you re-cast the type. 该表不会更改,因为您重新输入了类型。

For the second question, there is no difference. 对于第二个问题,没有区别。 If you mark a member function as virtual in the base class, it will be virtual in all child-classes as well. 如果在基类中将成员函数标记为virtual ,则在所有子类中也将其虚拟。 It's just that some people prefer to mark the functions in the child-classes virtual too. 只是有些人也喜欢将子类中的功能标记为virtual It can actually be good because then you don't have to check the base-class to see which functions are virtual and which are not. 它实际上可能很好,因为这样您就不必检查基类即可查看哪些函数是虚拟的,哪些不是。

And for the third question. 第三点。 Yes, virtual functions are calculated runtime using the table as described above, while non-virtual functions are determined at compilation time. 是的,虚拟函数是使用如上所述的表在运行时计算的,而非虚拟函数是在编译时确定的。

Question 1. 问题1

((Student*)c)->saySomething(); ((学生*)c)-> saySomething();

Why do I get "I am a CS Student."? 为什么会收到“我是一名CS学生”? I expected "I am a Student." 我期望“我是学生”。 since I specify virtual keyword only for the Person. 因为我只为Person指定了虚拟关键字。

In C++, if the base class specifies that a function is virtual , then you don't need the virtual keyword in any derived classes for member functions with the same signature. 在C ++中,如果基类指定一个函数为virtual ,则对于具有相同签名的成员函数,您不需要任何派生类中的virtual关键字。 You can include it if you want to (and it's generally good practice to do so), but it's optional. 您可以根据需要添加它(通常这样做是一种很好的做法),但这是可选的。

Question 2. 问题2。

I saw some example on the web page that mentions virtual keyword to only base case. 我在网页上看到了一些示例,其中仅将虚拟关键字提到了基本情况。 Also, I saw some example that mentions virtual keyword to all base case and derived classes. 另外,我看到了一些在所有基本案例和派生类中提及虚拟关键字的示例。 What's the difference between these two? 两者有什么区别?

As above: there is no difference. 如上所述:没有区别。 If the base class says a method with a particular signature is virtual, then that applies to all derived classes too. 如果基类说具有特定签名的方法是虚拟的,则该方法也适用于所有派生类。

Question 3. 问题3。

virtual function is determined in run time. 虚拟功能是在运行时确定的。 What about non-virtual function? 非虚拟功能呢? Is it determined in compile time? 是在编译时确定的吗?

Yes. 是。 If your saySomething() function was non-virtual, then the calls would be resolved at compile-time, and the cast to Student* would mean you'd get the Student version of saySomething() . 如果您的saySomething()函数不是虚拟的,则调用将在编译时解决,并且将其saySomething()Student*意味着您将获得Student版本的saySomething()

Why do I get "I am a CS Student."? 为什么会收到“我是一名CS学生”? I expected "I am a Student." 我期望“我是学生”。 since I specify virtual keyword only for the Person. 因为我只为Person指定了虚拟关键字。

In C++, if you specify the virtual keyword in a base class, that method will automatically be made virtual in any subclasses as well. 在C ++中,如果在基类中指定了virtual关键字,则该方法也将自动在任何子类中变为虚拟。 (I won't try to speculate on why C++ works that way, but it does) (我不会试图推测为什么C ++可以那样工作,但是确实可以)

I saw an example that puts a virtual keyword to only base case. 我看到了一个将虚拟关键字仅置于基本情况下的示例。 Also, I saw an example that puts virtual keywords to all base case and derived classes. 另外,我看到了一个将虚拟关键字应用于所有基本案例和派生类的示例。 What's the difference between these two? 两者有什么区别?

Functionally there is no difference. 在功能上没有区别。 I think stylistically the latter one is a little better in terms of being self-documenting. 从风格上讲,我认为后者在自我记录方面要好一些。

virtual function is determined in run time. 虚拟功能是在运行时确定的。 What about non-virtual function? 非虚拟功能呢? Is it determined in compile time? 是在编译时确定的吗?

Correct. 正确。 In particular, the method implementation that gets called for a non-virtual method will be determined solely by the pointer type it was called through, rather than via dynamic lookup of the appropriate subclass method. 特别是,将为非虚拟方法调用的方法实现将完全由调用该方法的指针类型确定,而不是通过对适当子类方法的动态查找来确定。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM