什么是编译时多态,为什么它只适用于函数?
答案 0 :(得分:18)
回过头来,“编译时多态”意味着函数重载。它仅适用于函数,因为它们都可以超载。
在当前的C ++中,模板会改变它。 Neil Butterworth已经举了一个例子。另一个使用模板专业化。例如:
#include <iostream>
#include <string>
template <class T>
struct my_template {
T foo;
my_template() : foo(T()) {}
};
template <>
struct my_template<int> {
enum { foo = 42 };
};
int main() {
my_template<int> x;
my_template<long> y;
my_template<std::string> z;
std::cout << x.foo << "\n";
std::cout << y.foo << "\n";
std::cout << "\"" << z.foo << "\"";
return 0;
}
这应该会产生42
,0
和""
(一个空字符串) - 我们得到的结构对每种类型的行为都不同。
这里我们有类的“编译时多态”而不是函数。我想如果你想争论这一点,你可以声称这至少部分是构造函数(一个函数)至少在一种情况下的结果,但my_template
的专用版本甚至不是 一个构造函数。
编辑:至于为什么这是多态。我把“编译时多态”放在引号中是有原因的 - 它与普通的多态有些不同。尽管如此,我们的效果与我们对重载函数的期望相似:
int value(int x) { return 0; }
long value(long x) { return 42; }
std::cout << value(1);
std::cout << value(1L);
函数重载和特化会产生类似的效果。我同意,对于“多态”是否也适用于某些问题是开放的,但我认为它同样适用于另一个。
答案 1 :(得分:13)
使用编译时多态性通常意味着您可以拥有多个具有相同名称的函数,编译器将在编译时选择使用哪个函数,具体取决于参数:
void foo(int x);
void foo(float y);
//Somewhere else
int x = 3;
foo(x); //Will call first function
float y = 2;
foo(y); //Will call second function
据说函数foo
已经过载。各种类型的模板实例化也可以称为编译时多态性。
答案 2 :(得分:6)
编译时多态是一个引用C ++模板编程的术语。例如,在编译时,您可以通过它包含的内容确定std :: vector的实际类型:
std::vector <int> vi;
std::vector <std::string> vs;
我不确定为什么你认为它仅限于功能。
答案 3 :(得分:6)
仅适用于函数的是模板参数推导。如果我有一个功能模板:
template <typename T>
void foo(T &t);
然后我可以int a = 0; foo(a);
,这相当于int a = 0; foo<int>(a);
。编译器的意思是我的意思是foo<int>
。至少,它应该使用foo<int>
- 如果这不是我的意思那么运气不好,我可以写foo<unsigned int>(a);
或其他什么。
但是,如果我有一个类模板:
template <typename T>
struct Foo {
T &t;
Foo(T &t) : t(t) {}
T &getT() { return t; }
};
然后我不能int a = 0; Foo(a).getT();
。我必须指定Foo<int>(a)
。不允许编译器解决我的意思Foo<int>
。
所以你可能会说类模板比函数模板“更少多态”。多态通常意味着您不必编写代码来使对象的类型显式化。函数模板允许(在这种特定情况下),而类模板则不允许。
至于为什么会这样 - 标准是这样说的,我不知道为什么。通常的嫌疑人是:(a)实施起来太难了,(b)标准委员会认为它没用,或者(c)它在语言的其他地方产生了一些矛盾或含糊之处。
但你仍然可以用类做其他类型的多态:
template <typename T>
struct Foo {
T &t;
Foo(T &t): t(t) {}
void handleMany(int *ra, size_t s) {
for (size_t i = 0; i < s; ++i) {
t.handleOne(ra[i]);
}
}
};
这通常也称为编译时多态,因为就模板的作者而言,t.handleOne
可以是任何东西,并且在必要时它将被解析,在编译中“稍后”当Foo被实例化时。
答案 4 :(得分:3)
编译时多态性适用于函数和运算符重载。