C++ 函数重载和ODR如何共存?(C+;+;)
为什么在一个编译单元中定义多个同名函数不违反一个定义规则?编译器如何识别违反ODR和使用函数重载的代码之间的代码?在C++中定义了参数类型(以及C++ 17,异常规范)。p>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] )
因此,重载是可能的,因为即使名称相同,函数也不相同。一个定义规则意味着每个重载函数必须定义一次。因此,这并不矛盾。每个重载函数在某些方面有所不同,例如参数的数量或类型、是否存在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不仅仅适用于一个编译单元,它还适用于整个程序。)同名但不同参数的函数是不同的函数