为什么我们实际上有虚函数? [英] why do we actually have virtual functions?

查看:197
本文介绍了为什么我们实际上有虚函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是C ++的新手。

任何人都可以告诉我在c ++中方法覆盖和虚拟函数概念之间的区别。

Could anybody tell me the difference between method overriding and virtual function concepts in c++.

虚函数的功能可以在其派生类中被覆盖。
重定义派生类中的函数称为函数重写。

The functionality of virtual functions can be over-ridden in its derived classes. Redefining a function in a derived class is called function overriding.

为什么我们实际上有虚函数?

why do we actually have virtual functions?

推荐答案

摘要

在本文中,我们将讨论C ++中的虚拟函数。第零部分解释了如何声明和覆盖虚函数。第一部分尝试(也许失败)解释如何实现虚拟函数。第二部分是一个示例程序,它使用在零和一部分中定义的示例类。第三部分是每个虚拟函数 - 多态教程中给出的经典动物示例。

In this paper, we discuss virtual functions in C++. Part zero explains how virtual functions are declared and overridden. Part one attempts (and perhaps fails) to explain how virtual functions are implemented. Part two is a sample program that uses the example classes defined in parts zero and one. Part three is the classic animal example given in every virtual function - polymorphism tutorial.

PART ZERO

当且仅当它的声明是这样的时,一个类的方法被称为 virtual

A method of a class is said to be virtual if and only if its declared to be so.

class my_base
{
public:
            void non_virtual_test() { cout << 4 << endl; } // non-virtual
    virtual void virtual_test()     { cout << 5 << endl; } // virtual
};

(当然,我假设程序员以前没有做过 #define virtual 。)

(Of course, I am assuming the programmer did not previously do anything like #define virtual.)

重新声明并重新实现其基础之一的非虚方法的类称为 overload 。重新声明并重新实现其基础之一的虚拟方法的类称为覆盖该方法。

A class that redeclares and re-implements a non-virtual method of one of its bases is said to overload that method. A class that redeclares and re-implements a virtual method of one of its bases is said to override that method.

class my_derived : public my_base
{
public:
    void non_virtual_test() { cout << 6 << endl; } // overloaded
    void virtual_test()     { cout << 7 << endl; } // overriden
};

第一部

当编译器检测到一个类有虚方法时,它会自动向类的内存布局添加一个虚方法表(也称为 vtable )。结果类似于编译此代码所产生的结果:

When the compiler detects a class has virtual methods, it automatically adds a virtual method table (also known as vtable) to the class' memory layout. The result is similar to what would have been generated from compiling this code:

class my_base
{
//<vtable>
// The vtable is actually a bunch of member function pointers
protected:
    void (my_base::*virtual_test_ptr)();
//</vtable>

// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
    void virtual_test_impl() { cout << 5 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
    my_base() : virtual_test_ptr(&my_base::virtual_test_impl) {}

public:
    void non_virtual_test() { cout << 4 << endl; }
    // The interface of the virtual function is a wrapper
    // around the member function pointer.
    inline void virtual_test() { *virtual_test_ptr(); }
};

当编译器检测到一个类覆盖了一个虚方法时,它会替换vtable中的相关条目。结果类似于编译此代码所产生的结果:

When the compiler detects a class has overridden a virtual method, it replaces its associated entry in the vtable. The result is similar to what would have been generated from compiling this code:

class my_derived : public my_base
{
// The actual implementation of the virtual function
// is hidden from the rest of the program.
private:
    void virtual_test_impl() { cout << 7 << endl; }

// Initializing the real_virtual_test pointer in the vtable.
public:
    my_derived() : virtual_test_ptr(&my_derived::virtual_test_impl) {}

public:
    void non_virtual_test() { cout << 6 << endl; }
};

第二部

现在很明显,虚函数是使用vtables来实现的,vtables只是一堆函数指针,应该清楚这段代码的作用:

Now that it's clear that virtual functions are implemented using vtables, which are nothing but a bunch of function pointers, it should be clear what this code does:

#include <iostream>

using namespace std;

class my_base
{
    public:
            void non_virtual_test() { cout << 4 << endl; }
    virtual void virtual_test()     { cout << 5 << endl; }
};

class my_derived : public my_base
{
public:
    void non_virtual_test() { cout << 6 << endl; }
    void virtual_test()     { cout << 7 << endl; }
}

int main()
{
    my_base* base_obj = new my_derived();

    // This outputs 4, since my_base::non_virtual_test() gets called,
    // not my_derived::non_virtual_test().
    base_obj->non_virtual_test();

    // This outputs 7, since the vtable pointer points to
    // my_derived::virtual_test(), not to my_base::virtual_test().
    base_obj->virtual_test();

    // We shall not forget
    // there was an object that was pointed by base_obj
    // who happily lived in the heap
    // until we killed it.
    delete base_obj;

    return 0;
}

第三部

因为没有动物的例子,没有虚拟函数的例子。

Since no virtual function example is complete without an example with animals...

#include <iostream>

using namespace std;

class animal
{
public:
    virtual void say_something()
    { cout << "I don't know what to say." << endl
           << "Let's assume I can growl." << endl; }

    /* A more sophisticated version would use pure virtual functions:
     *
     * virtual void say_something() = 0;
     */
};

class dog : public animal
{
public:
    void say_something() { cout << "Barf, barf..." << endl; }
};

class cat : public animal
{
public:
    void say_something() { cout << "Meow, meow..." << endl; }
};

int main()
{
    animal *a1 = new dog();
    animal *a2 = new cat();
    a1->say_something();
    a2->say_something();
}

这篇关于为什么我们实际上有虚函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆