在C ++中使用虚拟关键字

时间:2013-08-07 13:04:37

标签: c++ polymorphism virtual-functions

据我所知,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;
}

5 个答案:

答案 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 ++的作者在这里做了很好的工作,通过使虚拟关键词继承分层。