C ++不支持非成员虚拟函数的原因是什么

时间:2019-04-30 07:24:28

标签: c++

我很想知道C ++中没有非成员虚拟函数的原因是什么。尤其要考虑到这样的事实,因为您可以定义一个虚拟成员函数,然后从非成员函数中调用它,从而在需要实现时只会增加代码层。

编辑: 仅供参考,您可以这样做:

String

编辑2: 在某些情况下,您确实需要虚拟多态性,因为下面的情况不能以类似的方式工作,因为它会打印Base,而如果您要使用上述代码调用它,则会以类似的方式调用它。打印派生。我相信这总结了问题的症结所在。

struct Base
{
    virtual void say() const
    {
        std::cout << "Base\n";
    }
};

struct Derived : public Base
{
    void say() const final
    {
        std::cout << "Derived\n";
    }
};

void say(Base* obj)
{
    obj->say();
}

say(static_cast<Base*>(new Derived()));

3 个答案:

答案 0 :(得分:4)

非成员函数不需要隐式this指针即可调用它。

但是虚函数需要一个this指针(即对象 instance ),以便多态性起作用。

有一个矛盾:因此不可能有一个多态的非成员函数。

答案 1 :(得分:1)

当您想在自由函数中使用多态时,基本上有两个选择。您可以重载该函数或调用虚函数:

#include <iostream>

struct base {
    virtual void func() = 0;
};

struct foo : base { void func() { std::cout << "foo\n"; } };
struct bar : base { void func() { std::cout << "bar\n"; } };

void f(foo& f) { f.func(); }
void f(bar& f) { f.func(); }

void g(base& b) { b.func(); }

int main() {
    foo a;
    bar b;
    f(a);
    f(b);
    g(a);
    g(b);
}

考虑到与成员函数的主要区别是隐式this参数,g实际上与我所谓的“虚拟自由函数”非常接近。但是,除此之外,C ++中没有虚拟的非成员函数。

答案 2 :(得分:1)

具有虚拟非成员函数在编译方面在技术上具有挑战性。

虚拟功能通常是通过vtable实现的。具有虚拟成员函数的类存储指向该vtable的指针,并且该vtable已添加了所有必需的函数。调用虚拟函数时,将在vtable中查找要调用的确切函数。

考虑一下:我正在用C ++写一个库。为了用户方便并减少编译时间,该库的分发方式为:

  • 库的头文件
  • 二进制文件,提供标题中定义的功能的实现。

那是什么问题?

这些二进制文件还将在头文件中包含具有虚函数的任何类的vtable。为了将虚拟函数添加到基类,编译器将必须读取和处理库文件的二进制表示,并修改vtable以添加必要的函数。

这将大大增加链接的复杂性(使编译器部分负责),并且膨胀可执行文件的大小(任何动态加载的库都必须静态链接,因为编译器可能没有权限修改它们内容)。

有技术上的解决方法吗?

是的,尽管这将要求类的实现出现在头文件中,例如模板。另外,新的模块系统可以通过不再需要单独的实现文件来提供一种实现此功能的方法。

即使那样,编译器开发人员也需要大量工作,并且对该功能的需求并不高。此功能提供的主要好处是能够快速轻松地为特定的派生类重载函数,该派生类本身被认为是某种代码味道(因为您接近破坏封装的作用-库编写器编写了返回指针的函数例如,对基类的更改可能想要更改它返回的派生类)。