据我所知,C ++实现了虚拟函数的运行时多态性,虚拟关键字是继承的,但我没有在派生类中看到虚拟关键字的使用。
e.g。在下面的情况下,即使你在派生类中删除虚拟关键字仍然ptr-> method()调用转到derived :: method。那么这个虚拟关键字在派生类中做了多少额外的工作呢?
#include<iostream>
using namespace std;
class base
{
public:
virtual void method()
{
std::cout << std::endl << "BASE" << std::endl;
}
};
class derived: public base
{
public:
virtual void method()
{
std::cout << std::endl << "DERIVED" << std::endl;
}
};
int main()
{
base* ptr = new derived();
ptr->method();
return 9;
}
答案 0 :(得分:22)
如果派生类的方法按名称和签名匹配其中一个基类的虚方法,并且匹配的方法是虚拟的,那么派生类的方法也会变为虚拟。因此,从技术上讲,没有必要在派生类中标记“虚拟”这样的方法。但是,在C ++ 11之前,它曾经是一个很好的实践,因为它对那些阅读代码的人来说是一个很好的暗示(很难记住基类的所有虚函数)。
从C ++ 11开始,在派生类中有两个额外的关键字可以帮助实现可读性和代码健壮性。他们是“覆盖”和“最终”。例如,在派生类的方法中放置«override»可确保基类的相应方法实际上是虚拟的。 «final»关键字执行相同的操作,它可以防止方法被进一步覆盖。
我还在我的博客here中用更真实的理由和代码示例写了这篇文章。
希望它有所帮助。祝你好运!
答案 1 :(得分:8)
virtual
仅在基类声明中是必需的。它在派生类中是可选的,在这些情况下可能主要用作提醒。
C ++ 11引入override
使事情更加明确:它明确地将派生类中的方法标记为对基类的virtual
方法的重写。
答案 2 :(得分:7)
无。只是为了帮助提醒您哪些功能是虚拟的。
答案 3 :(得分:0)
虚拟关键字在驱动器类中是可选的,因为根据规则,当您使用具有虚函数的基类驱动类时,并且当您在驱动器类编译器中重写虚函数时,隐式地将虚拟关键字与函数一起分配。因此,您无需显式分配虚拟关键字。但在多级继承期间,此关键字是必需的。
示例:
在您的代码中,我们添加了此代码。
class derived: public base {
public:
virtual void method() { // In this line virtual keyword is optional.
std::cout << std::endl << "DERIVED :: method function" << std::endl;
}
virtual void display() {
std::cout << std::endl << "DERIVED :: display function" << std::endl;
}
};
class deriveChild: public derived {
public:
void method() {
std::cout << std::endl << "DERIVECHILD :: method" << std::endl;
}
void display() {
std::cout << std::endl << "DERIVECHILD:: display" << std::endl;
}
};
在main()中如果使用下面的代码,它会给你不同的输出。
base *ptr = new deriveChild();
ptr->method(); // will compile and execute
ptr->display(); // will generate error because display() is not part of base class.
现在,如果您想使用deriveChild类的display(),请使用此代码。
derived *ptr = new deriveChild();
ptr->method(); // Compile and Execute
ptr->display(); // Compile and Execute
答案 4 :(得分:0)
派生类中的隐式虚方法在派生类中是虚拟的,不需要将它们显式定义为虚拟。如果声明它将是冗余声明。
ptr->method();
当编译器遇到上述声明时
- &GT;它会尝试解析上面的语句,因为method()函数是虚函数,编译器推迟解析该调用运行时。
- &gt;在运行时创建派生类的对象时,编译器现在将知道此方法是派生类。
此虚拟关键字在派生类中的额外功能是什么?
考虑到这种情况,还有一个名为Derived2的派生类inherting form derived,它有自己的虚方法。
class derived2: public derived
{
public:
virtual void method()
{
std::cout << std::endl << "DERIVED2" << std::endl;
}
};
如果您在main中调用方法(),如下所示
int main()
{
base* ptr = new derived2();
ptr->method(); //derived2 class method() will get called
return 9;
}
如果derived2中的method()默认情况下不是虚拟的,那么最终会调用方法()的派生版本,从而失去运行时多态性的好处。
因此,c ++的作者在这里做了很好的工作,通过使虚拟关键词继承分层。