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

iht*_*wot 19 c++ polymorphism compile-time

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

Jer*_*fin 19

回过头来,"编译时多态"意味着函数重载.它仅适用于函数,因为它们都可以超载.

在当前的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;
}
Run Code Online (Sandbox Code Playgroud)

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

这里我们有类的"编译时多态"而不是函数.我想如果你想争论这一点,你可以声称这至少部分是构造函数(一个函数)至少在一种情况下的结果,但是专门的版本my_template甚至没有构造函数.

编辑:至于为什么这是多态.我把"编译时多态"放在引号中是有原因的 - 它与普通的多态有些不同.尽管如此,我们得到的效果类似于我们对重载函数的期望:

int value(int x) { return 0; }
long value(long x) { return 42; }

std::cout << value(1);
std::cout << value(1L);
Run Code Online (Sandbox Code Playgroud)

函数重载和特化给出了类似的效果.我同意,对于"多态"是否也适用于某些问题是开放的,但我认为它同样适用于另一个.


And*_*nck 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
Run Code Online (Sandbox Code Playgroud)

该功能foo据说是超载的.各种类型的模板实例化也可以称为编译时多态性.


小智 6

编译时多态是指C++模板编程的术语.例如,在编译时,您可以通过它包含的内容确定std :: vector的实际类型:

std::vector <int> vi;
std::vector <std::string> vs;
Run Code Online (Sandbox Code Playgroud)

我不确定你为什么认为这仅限于功能.


Ste*_*sop 6

仅适用于函数的是模板参数推导.如果我有一个功能模板:

template <typename T> 
void foo(T &t);
Run Code Online (Sandbox Code Playgroud)

然后我就能做到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; }
};
Run Code Online (Sandbox Code Playgroud)

然后我做不到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]);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)

这通常也称为编译时多态,因为就模板的作者而言,t.handleOne可能是任何东西,并且在必要时它将被解析,在Foo被实例化时在编译中"稍后".