考虑我们有接受一些基本类型的函数:
void print(const base&);
然后,我们在另一个 header 中定义了一个继承自 base
的结构,称之为 derived
。最后,在第三个 header 中,我们有一个 print
的重载,它接受一个 derived
。总的来说,我们有这个:
// header 1
struct base {};
void print(const base&);
// header 2
#include "header 1"
struct derived:base{};
// header 3
struct derived;
void print(const derived&);
重要的是要注意 print
函数是在不同的 TU 中定义的。现在比较这两个翻译单元:
// source 1
#include "header 2"
void foo() {
derived d;
print(d);
}
// source 2
#include "header 2"
#include "header 3"
void bar() {
derived d;
print(d);
}
对 print
的调用看起来是一样的,但是第一个源文件调用 print(const base&)
而第二个调用 print(const derived&)
。这种行为是否合法且符合标准?还是我在某个时候陷入了 UB?
如果 print
是一个模板函数,那么我们用一个非模板方法重载 print
会怎么样(忽略模板方法可能被选择为非模板作为它可能匹配得更好,假设我们正确地重载它),合法性会改变吗?
提出这个问题的部分原因是想知道什么是合法和健全的定制来源,什么不是。标准库倾向于类模板的部分/显式特化。
最佳答案
这是合法的,但很脆弱。
如果您的 foo
作为内联函数在 header 中,这将是有问题的,因为您可能会破坏 ODR(单一定义规则)。
foo
然后会调用void print(const base&);
或 void print(const derived&);
取决于之前的包含。
foo
可以重写为:
void foo() {
derived d;
print(static_cast<Base&>(d));
}
明确选择哪个重载。
What if print was a template function instead, so that we overloaded print
template <typename T> void print(const T&);
有了重载,就没有问题了。
通过特化,它将成为 foo
和 bar
会用 print<derived>
, 但使用不同的定义。
关于c++ - 有条件地添加到重载集是否合法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48942170/