什么是编译时多态,为什么它只适用于函数?

时间:2009-12-10 14:51:40

标签: c++ polymorphism compile-time

什么是编译时多态,为什么它只适用于函数?

5 个答案:

答案 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;
}

这应该会产生420""(一个空字符串) - 我们得到的结构对每种类型的行为都不同。

这里我们有类的“编译时多态”而不是函数。我想如果你想争论这一点,你可以声称这至少部分是构造函数(一个函数)至少在一种情况下的结果,但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)

编译时多态性适用于函数和运算符重载。

阅读此http://cpp-tutorial.cpp4u.com/OOP_polymorphism.html