在头文件中定义的非内联虚函数 [英] non-inlined virtual function defined in header file

查看:145
本文介绍了在头文件中定义的非内联虚函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


单一定义规则规定:

在整个程序中,对象
或非内联函数不能有多个定义。 (从
维基百科)

The One Definition Rule states that:
In the entire program, an object or non-inline function cannot have more than one definition. (from Wikipedia)

好吧,我知道如果一个成员函数在头文件中定义, ,和ODR确定。

Well, I know that if an member function is defined in a header file, it's implicitly inlined, and it's ok with the ODR.

但是虚拟函数呢?我们知道,如果一个虚函数被称为多态,它不能被内联。如果这样的虚拟函数在头文件中定义,那么是否会违反ODR?

But what about virtual functions? We know that if an virtual function is called polymorphically, it can't be inlined. if such a virtual function is deined in a header file, will that violate the ODR ?

例如:

//derived.hpp
#include <iostream>
class Base {
public:
  virtual ~Base() {}
  virtual void vfunc() {
    std::cout << "Base::vfunc()\n";
  }
};

class Derived : public Base {
public:
  virtual ~Derived() {}

  virtual void vfunc() {
    std::cout << "Derived::vfunc()\n";
  }
};

//foo.cpp

#include "derived.hpp"
void func() {
  Base* ptr = new Derived();
  ptr->vfunc(); //polymorphic call, can't be inlined
  delete ptr;

  ptr = new Base();
  ptr->vfunc();
  delete ptr;
}
//main.cpp

#include "derived.hpp"

int main() {
  Base* ptr = new Derived();
  ptr->vfunc(); //polymorphic call, can't be inlined
  delete ptr;

  ptr = new Base();
  ptr->vfunc();
  delete ptr;
  return 0;
}

我很好奇:

vfunc(和dtor)在foo.cpp和main.cpp中被多态(不是内联)调用,这意味着它在整个程序中定义了两次,所以它违反了ODR,不是吗?它如何编译(链接)?

vfunc(and dtor) is called in both foo.cpp and main.cpp polymorphically(not inlined), which means it's defined twice in the entire program, so it violates the ODR, isn't it? How does it compiles(link) ?

我刚看到:


多个定义

More than one definition

在某些情况下,可以有多个类型定义或
模板。由多个头文件和源
文件组成的程序通常具有多个类型的定义,而不是
每个翻译单元多于一个定义。如果程序包含
多于一个类型的定义,那么每个定义必须是
等价的(也取自维基百科)

In certain cases, there can be more than one definition of a type or a template. A program consisting of multiple header files and source files will typically have more than one definition of a type, but not more than one definition per translation unit. If a program contains more than one definition of a type, then each definition must be equivalent (also taken from Wikipedia)

某些情况是什么?上述情况是否是其中之一?

What are the certain cases? Whether the above case be one of it?

推荐答案


vfunc(和dtor) foo.cpp和main.cpp多态(不内联),这意味着它在整个程序中定义了两次。

vfunc(and dtor) is called in both foo.cpp and main.cpp polymorphically(not inlined), which means it's defined twice in the entire program,

调用不意味着定义。因此,函数调用不会告诉你ODR是否被违反。

first of all: calling does not mean definition. So the function calls do not tell you wether the ODR is violated.


因此它违反了ODR,不是吗?

so it violates the ODR, isn't it? How does it compiles(link) ?

它编译,因为类定义中定义的成员函数被隐式声明为内联,因此不会违反ODR。这适用于 vfunc 定义以及dtors,所以你在这里很好。

It compiles, because member functions defined inside a class definition are implicitly declared inline and therefore don't violate the ODR. That applies for both vfunc definitions as well as for the dtors, so you are good here.

注意 inline (显式或隐式)和实际内联的函数之间有区别。编译器决定内联函数一次可能受到 inline 关键字的影响,但它只是一个提示。这些天,优化器可以比任何人更好地预测,当不内联是一个不错的选择,所以编译器可以忽略该提示,每当它认为合适,它可以内联函数已被声明内联的 。因此,对于现代编译器, inline 只是一种遵守ODR函数的方法,而不是隐式声明 inline

Note: There is a difference between an function declared inline (explicitly or implicitly) and a function that actually gets inlined. The compiler's decision to inline a function once could be influenced by the inline keyword, but it was and is only a hint. These days optimizers can predict better than any human when and when not inlining is a good choice, so the compiler can ignore that hint whenever it sees fit, and it can inline functions that have not been declared inline. So with modern compilers, inline is just a means to obey the ODR for functions, that are not declared inline implicitly.

更新:因此,在您的情况下,函数被隐式声明为 单位(两个.cpp的),它不会被编译器内联。在这种情况下,链接器会看到函数的符号两次,但是它不会因为内联声明而抱怨多个符号。

Update: So in your case, the function is declared inline implicitly, the definition is included in two translation units (the two .cpp's) and it does not get inlined by the compiler. In this case, the linker will see the symbol for the function twice, but it will not complain about multiple symbols because of the inline declaration.

这篇关于在头文件中定义的非内联虚函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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