Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.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++ 函数重载和ODR如何共存?(C+;+;)_C++_Function_Compilation_Overloading_One Definition Rule - Fatal编程技术网

C++ 函数重载和ODR如何共存?(C+;+;)

C++ 函数重载和ODR如何共存?(C+;+;),c++,function,compilation,overloading,one-definition-rule,C++,Function,Compilation,Overloading,One Definition Rule,为什么在一个编译单元中定义多个同名函数不违反一个定义规则?编译器如何识别违反ODR和使用函数重载的代码之间的代码?在C++中定义了参数类型(以及C++ 17,异常规范)。p> 因此,重载是可能的,因为即使名称相同,函数也不相同。一个定义规则意味着每个重载函数必须定义一次。因此,这并不矛盾。每个重载函数在某些方面有所不同,例如参数的数量或类型、是否存在c/v限定符(在参数声明或类成员函数本身中)等等 有时初学者考虑这些函数声明作为重载函数< /p>的声明。 void f( int a[100] )

为什么在一个编译单元中定义多个同名函数不违反一个定义规则?编译器如何识别违反ODR和使用函数重载的代码之间的代码?在C++中定义了参数类型(以及C++ 17,异常规范)。p>
因此,重载是可能的,因为即使名称相同,函数也不相同。

一个定义规则意味着每个重载函数必须定义一次。因此,这并不矛盾。每个重载函数在某些方面有所不同,例如参数的数量或类型、是否存在c/v限定符(在参数声明或类成员函数本身中)等等

有时初学者考虑这些函数声明作为重载函数< /p>的声明。
void f( int a[100] );
void f( int a[10] );
void f( int a[] );
void f( int *a );
void f( int *a );
void f( const int *a );
但是,编译器隐式地将数组类型的参数调整为数组元素类型的指针

您可以在程序中包含所有这些(冗余)声明,但必须只定义一次函数

因此,上面的声明声明了同一个函数,其参数由编译器调整为
int*
类型

考虑到这些函数声明声明了两个重载函数

void f( int a[100] );
void f( int a[10] );
void f( int a[] );
void f( int *a );
void f( int *a );
void f( const int *a );
(这里指针本身不是常量,而是指针指向的数据是常量)

而这两个宣言,

void f( int x );
void f( const int x );
声明同一个函数,因为当编译器确定函数是重载的还是相同的时,常量限定符将被丢弃

当函数参数具有函数类型时,也会出现同样的混淆。比如说

void f( void g() );
void f( void ( *g )() );
同样,编译器隐式地调整函数类型的参数以指向函数的指针

这是一个演示程序

#include <iostream>

void f( void g() );
void f( void ( *g )() );

void g() { std::cout << "Hello Philippa Richter\n"; }

void f( void g() )
{
    g();
}

int main()
{
    f( g );
}

请注意,函数
f
虽然声明了三次,但定义了一次,包括同时是其定义的声明。

一个定义规则不适用于具有相同名称的事物;它适用于假装相同的事物

两个名为
foo
(在全局范围内声明,位于命名空间、类或函数之外)的类假装相同;它们必须是一样的。如果你改变一个程序中的定义,你就对编译器撒谎。(这就像是根据术语的特殊定义与某人争论,然后假装已经证明某些东西适用于常规术语。)


两个名为
bar
的函数不会假装相同,除非它们具有相同的参数列表。

您问的是两个非常不同的问题。1)ODR是什么,它如何应用于重载函数?2) 超载是什么时候的好习惯?(ODR不仅仅适用于一个编译单元,它还适用于整个程序。)同名但不同参数的函数是不同的函数