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

C++ 什么是编译时多态性?为什么它只适用于函数?,c++,polymorphism,compile-time,C++,Polymorphism,Compile Time,什么是编译时多态性?为什么它只适用于函数?编译时多态性适用于函数和运算符重载 阅读此 < P>编译时多态性是指C++模板编程的一个术语。例如,在编译时,通过std::vector包含的内容确定其实际类型: std::vector <int> vi; std::vector <std::string> vs; std::vector vi; std::向量vs; 我不知道您为什么认为它仅限于函数。对于编译时多态性,一个通常意味着可以有几个同名函数,编译器将在编译时根据参

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

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


<>阅读此

< P>编译时多态性是指C++模板编程的一个术语。例如,在编译时,通过std::vector包含的内容确定其实际类型:

std::vector <int> vi;
std::vector <std::string> vs;
std::vector vi; std::向量vs;
我不知道您为什么认为它仅限于函数。

对于编译时多态性,一个通常意味着可以有几个同名函数,编译器将在编译时根据参数选择使用哪一个:

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
被称为重载。各种类型的模板实例化也可以称为编译时多态性。

早在“编译时多态性”意味着函数重载的时候。它只适用于函数,因为它们是所有可以重载的函数

在当前的C++中,模板改变了。尼尔·巴特沃斯已经举了一个例子。另一个使用模板专门化。例如:

#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;
}

函数重载和专门化也产生了类似的效果。我同意“多态性”是否适用于任何一个函数都有问题,但我认为它同样适用于其中一个函数。

只适用于函数的是模板参数推导。如果我有一个函数模板:

template <typename T> 
void foo(T &t);
template <typename T>
struct Foo {
    T &t;
    Foo(T &t) : t(t) {}
    T &getT() { return t; }
};
那我就不能做
inta=0;Foo(a.getT()。我必须指定
Foo(a)
。编译器不允许计算出我的意思是
Foo

因此,您可能会说类模板比函数模板“多态性更小”。多态性通常意味着您不必编写代码来明确对象的类型。函数模板允许这样做(在这种特殊情况下),而类模板则不允许

至于为什么会这样——标准上这么说,我不知道为什么。通常的怀疑是(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]);
        }
    }
};
模板
结构Foo{
T&T;
Foo(T&T):T(T){}
空心把手(内*外,尺寸){
对于(尺寸i=0;i

这通常也称为编译时多态性,因为就模板的作者而言,
t.handleOne
可以是任何东西,必要时将在“以后”解决它在编译中,当Foo被实例化时。

这个问题看起来几乎完全嵌入到教科书中。你能描述一下你看到的矛盾吗?-也许这有助于回答你的实际问题。我的课本中有一些含糊不清的地方,或者我误解了我在读什么,所以我想我在这里问。我想课堂是我唯一能想到的事情,但这似乎不正确。@nmr我同意。编译器确实根据我们提供的类型T选择实例化类的哪个版本,这难道不意味着类模板也存在编译时多态行为吗?主要是因为我在类中被告知它仅限于函数。我不完全理解为什么它只限于函数。@Neil我同意你的看法。类模板似乎也存在编译时多态性。那么类模板呢?编译器确实根据我们提供的类型T选择实例化类的哪个版本,那么这是否意味着类模板也存在编译时多态行为?@captonssj,我想说是的,它们存在。这更像是一个运行时多态性示例吗?我想我被这两个不同的东西弄糊涂了,即运行时多态性和编译时多态性…唉…我的例子中的代码是编译时的,即应该调用哪个重载函数是在编译时确定的。我认为根据标准委员会的说法,它是有用的,因为他们选择通过std::mem_-fun/std::mem_-fun\t的实现来解决这个特定问题。基本上他们所做的是:模板std::mem_fun_t mem_fun(const_Tx&t){return std::mem_fun_t(t);}是的,迭代器适配器也是如此:
back_inserter
返回
back_insert_迭代器
。当我说“和”时,我的意思是“这就是清单”,而不是“这些都是真的”。我认为(a)也不太可能,所以不是(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]);
        }
    }
};