Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;执行多态性时是否接受内联虚拟函数? //header.h #包括 使用名称空间std; 结构基{ 虚拟void vf(); }; 派生结构:基{ 虚拟void vf(); }; 内联void Base::vf(){ 一个定义规则是强制的。它是C++所必需的。给定的对象或函数必须精确定义一次。删除内联< /COD>关键字(在您的情况下)违反了该规则,使生成的程序不正确。_C++ - Fatal编程技术网

C++;执行多态性时是否接受内联虚拟函数? //header.h #包括 使用名称空间std; 结构基{ 虚拟void vf(); }; 派生结构:基{ 虚拟void vf(); }; 内联void Base::vf(){ 一个定义规则是强制的。它是C++所必需的。给定的对象或函数必须精确定义一次。删除内联< /COD>关键字(在您的情况下)违反了该规则,使生成的程序不正确。

C++;执行多态性时是否接受内联虚拟函数? //header.h #包括 使用名称空间std; 结构基{ 虚拟void vf(); }; 派生结构:基{ 虚拟void vf(); }; 内联void Base::vf(){ 一个定义规则是强制的。它是C++所必需的。给定的对象或函数必须精确定义一次。删除内联< /COD>关键字(在您的情况下)违反了该规则,使生成的程序不正确。,c++,C++,运行时多态性和虚拟函数分派发生在运行时。只有当程序格式正确时,才能进入运行时部分。如果它破坏了ODR,则表示格式不正确,因此运行时多态性和虚拟函数分派如何工作就成了一个有争议的问题。如果程序格式不正确,则将无法运行任何程序,也没有基本的p一点也不 的确,ODR冲突不需要诊断,但生成的代码仍然被破坏。请向编译器写一封感谢信,提醒您注意此问题。由于代码当前已编写,成员函数在header.h中定义,并标记为inline。从这个角度看,这没问题语言定义:inline表示“可以有多个[相同]的函数定义”。

运行时多态性和虚拟函数分派发生在运行时。只有当程序格式正确时,才能进入运行时部分。如果它破坏了ODR,则表示格式不正确,因此运行时多态性和虚拟函数分派如何工作就成了一个有争议的问题。如果程序格式不正确,则将无法运行任何程序,也没有基本的p一点也不


的确,ODR冲突不需要诊断,但生成的代码仍然被破坏。请向编译器写一封感谢信,提醒您注意此问题。

由于代码当前已编写,成员函数在
header.h
中定义,并标记为
inline
。从这个角度看,这没问题语言定义:
inline
表示“可以有多个[相同]的函数定义”。从维护的角度来看,这会使事情变得更困难。特别是,当您这样做时,每次更改这些函数的实现时,您都必须重新编译使用该头的所有源文件。将这些函数的定义放入它们自己的源文件意味着您只需重新编译这些文件这改变了

如果您不想将函数标记为
内联
(并且不想在类定义中定义它们,这会使它们隐式内联),然后您必须将每个函数定义放入一个源文件中。有用的第一步是在单个源文件中定义一个类的所有非内联成员函数。因此您的
source2.cpp
可能如下所示(是的,这是来自两个类的成员函数):

#包括“header.h”
#包括
void Base::vf(){

std::cout
inline
关键字如今在很大程度上与内联优化无关。它主要是关于一个定义规则,关于链接器是否会忽略重复的定义或抱怨重复的定义。我有什么错误吗?当你删除
inline
关键字时,你也应该从标题中移动例程<将.h
文件编码到关联的
.cpp
文件中。顺便说一句,对虚拟函数的调用在运行时总是被解析的说法是不正确的。如果优化器可以证明指针总是指向特定派生类的实例,它可以“DeviceAlize”调用-生成对该类重载的直接调用。作为进一步优化,重载可以内联。因此,在您的示例中,优化器可以将
pb->vf()
转换为
static\u cast(pb)->Derived::vf()
,然后可能内联
Derived::vf())
@IgorTandetnik即使我在示例中包含两次,每个vf是否仍有一个副本?理论上,这是一个与程序员无关的实现细节。编译器和链接器必须以某种方式进行安排。在实践中,典型的实现会在每个
.obj
文件中放置函数体的副本根据包含其定义的翻译单元进行评级,然后链接器将丢弃除一个副本以外的所有副本。我了解到
inline
是否被接受取决于编译时的编译器,虚拟机制是运行时的决定。因此我将定义放在头文件中进行实验,以查看编译器是否忽略 >内联< /代码>等同于删除<代码>内联关键字。@ SkkGaWa--如果您有一个编译器,它不允许<代码>内联这里写,它是严重缺陷的。这正是内联的意思。我想知道现代C++中的<代码>内联< /COD>关键字没有什么。用于扩展代码(函数体)在调用函数的时候。这更像是允许多个定义,但在程序中仍然有一个副本吗?@sakugawa--是的,没错。这最初是一个关于内联扩展函数的提示,暗示允许多个相同的定义。编译器很快对内联函数变得更聪明了。这个提示变成了intless,但源代码中允许多个定义的含义仍然存在。如果函数以内联方式展开,则副本的数量与展开的数量相同。如果需要,也可能有一个单独的函数版本正常调用。
//header.h
#include<iostream>
using namespace std;
struct Base {
    virtual void vf();
};
struct Derived :Base {
    virtual void vf();
};
inline void Base::vf() {
    cout << "Base::vf()" << endl;
}
inline void Derived::vf() {
    cout << "Derived::vf()" << endl;
}

//source.cpp
#include"header.h"
int main() {
    Base *pb = new Derived;
    pb->vf();
}

//source2.cpp
#include"header.h"
#include "header.h"
#include <iostream>

void Base::vf() {
    std::cout << "Base::vf()\n";
}

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