【问题标题】:calling virtual function by vptrvptr调用虚函数
【发布时间】:2018-11-09 19:18:41
【问题描述】:

我最近在阅读有关 C++ 中的虚函数和继承的内容,最后读到了 vptr 和 VTABLE。

我的问题与使用 vprt 调用派生对象的方法有关。

我解释一下,下面是我的代码:

    #include <iostream>
    using namespace std;


    class base
    {
    public:
        void fun_1() { cout << "base-1\n"; }
        virtual void fun_2() { cout << "base-2\n"; }
        virtual void fun_3() { cout << "base-3\n"; }
        virtual void fun_4() { cout << "base-4\n"; }
    };

    class derived : public base
    {
    public:
        void fun_1() { cout << "derived-1\n"; }
        void fun_2() { cout << "derived-2\n"; } 
        void fun_4() { cout << "derived-4\n"; }
    };

    int main()
    {
        base *p;
        derived obj1;
        p = &obj1;

        void(*firstfunc)() = (void(*)(void))(*(int*)*(int*)p);
        firstfunc();
    }

结果是:

派生-2

好的,到现在为止,我对(void(*)(void))(*(int*)*(int*)p)的操作还是很模糊,但是我怎么能调用第二个函数呢?

谢谢

【问题讨论】:

  • 你是从哪里想到写void(*firstfunc)() = (void(*)(void))(*(int*)*(int*)p);的?你期望它做什么?
  • Vtables 和 vptrs 是内部实现细节,此代码取决于未定义的行为。
  • 不需要(实际上也没有保证支持)访问任何vtable;只需执行p-&gt;fun_1()p-&gt;fun_2();该语言会为您处理动态绑定。
  • @Blood-HaZaRd 从该页面:许多编译器将虚拟表指针作为对象的最后一个成员;其他编译器将其作为第一个
  • 如果你认为你需要关心这些东西的内部结构,那就停下来。你这样做是错的。虽然了解事物是如何“在幕后”实现的可能很有用,但作为语言的用户,您永远不需要知道或关心。

标签: c++ polymorphism virtual


【解决方案1】:

如何调用第二个函数?

你可以这样称呼它:

p->fun_2();

打印:

derived-2

虚拟表和虚拟函数指针是编译器的实现细节。一般来说,您不应该关心这些实现细节,因为如果您这样做,您就会编写不可移植的代码。实际上,我什至不确定您的代码是否具有未定义的行为,如果确实如此,那么即使将 vpointer 放置在您期望的位置的编译器也可能会打印垃圾。无论如何,除非你需要,否则不要这样做,这实际上是永远不会的;)。

作为旁注,如果你使用别名,函数指针就会失去很多可怕的东西,例如

using base_mem_fun = void (base::*)();
base_mem_fun first_base = &base::fun_1;
(p->*first_base)();

打印:

base-1

【讨论】:

    猜你喜欢
    • 2014-06-16
    • 1970-01-01
    • 2012-02-06
    • 2012-02-24
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 2016-06-12
    • 2011-08-06
    相关资源
    最近更新 更多