C++ 具有模板成员函数的类,是同一个类吗?
我对模板成员函数有点困惑,让我们假设我们有一个带有模板成员函数的奇怪结构,如下所示:C++ 具有模板成员函数的类,是同一个类吗?,c++,templates,C++,Templates,我对模板成员函数有点困惑,让我们假设我们有一个带有模板成员函数的奇怪结构,如下所示: struct Foo { template <typename T> void f(T t) {}; }; 另一方面,其他Foo实例似乎只有一个版本的f函数。显然,由于成员函数的不同,每个实例的基类型是不同的 [1] Foo::f(float t); [2] Foo::f(double t); [3] Foo::f(long t); ?f函数的实例在哪里?显然,我们只能从第一个Foo实例
struct Foo
{
template <typename T> void f(T t) {};
};
另一方面,其他Foo实例似乎只有一个版本的f函数。显然,由于成员函数的不同,每个实例的基类型是不同的
[1] Foo::f(float t);
[2] Foo::f(double t);
[3] Foo::f(long t);
?f函数的实例在哪里?显然,我们只能从第一个Foo实例获取Foo::f(int t)函数的地址,因为该函数只属于该实例;其他功能也一样
[1] Foo::f(float t);
[2] Foo::f(double t);
[3] Foo::f(long t);
提前感谢。所有重载都是由编译器为
Foo::f
成员函数生成的,您可以将其视为已手动写出所有重载
重载生成(模板实例化)不是基于实例的,而是基于类的,类本身会将所有模板实例化飞溅(就像在类体中为给定类型T编写了不同类型的所有重载一样)
因此,在你的情况下:
struct Foo
{
template <typename T> void f(T t) {};
};
structfoo
{
模板空位f(T){};
};
将成为(概念上的)
structfoo
{
void f(int t){};
空f(chart){};
void f(float t){};
...
///在代码中的任何地方,f的所有其他用法都具有不同的类型。
};
这就是人们反对模板的原因之一,它被称为“代码膨胀”。所有
Foo
实例都有所有重载,它们都是相同的类型,因为Foo
本身不是模板类
函数在编译时在目标代码中实例化
?Foo类的所有实例都来自同一个类?答案似乎是肯定的
是的,所有实例都属于同一类型
但是。。。第一个Foo实例的末尾有两个f成员函数的重载
重载是按类型而不是按实例进行的。该类型将包含所有重载,而不管实例化模板函数的对象是什么
?f函数的实例在哪里?显然,我们只能从第一个Foo实例获得Foo::f(int t)函数的地址,因为该函数只属于该实例;其他功能也一样
[1] Foo::f(float t);
[2] Foo::f(double t);
[3] Foo::f(long t);
它们由编译器实例化(编译成二进制代码),这不是一个正确的问题(二进制代码除外)。成员函数的地址只能从类中获取,不能从任何实例中获取,正如我已经提到的,成员函数是按类型的,而不是按类型的实例获取。让我们看一个不同的示例:
struct Foo
{
void f(int);
void f(double);
};
// ...
Foo foo1, foo2;
foo1.f(3);
foo2.f(3.0);
这与您自己的版本完全类似,只是编译器不创建方法f()
的新实例化。我们只在foo1
上调用方法f(int)
,在foo2
上调用方法f(double)
。你认为他们现在有不同的类型吗,仅仅因为我们没有在每个实例上调用所有的方法
方法与类关联,而不是与实例关联。您的代码生成的所有方法重载都是类
Foo
的方法,并且您的所有实例都具有相同的类型。在我看来,这两个示例并不完全相似。只是因为在您的示例中,Foo结构有两个“从Begging”创建的函数成员,而在模板版本中,您不知道在编译时之前创建了哪些成员。“成员函数的地址只能从类中获得”,我们假设要使用浮点函数作为回调,我们可以定义一个float成员函数指针:void(Foo::*CallBack)(float)=&Foo::f
并让它指向foo的任何f成员,因为它们都有一个带float的f成员(由于@Akanksh提到的代码膨胀):foo&foo=V.at(0);(foo.*回调)(12.34f)代码>@PaperBirdMaster:我不明白这个问题。指向成员的指针必须从类中获取:&Foo::f
(注意Foo
,并且必须应用于实例:(Foo.*回调)
。你担心什么?这是一个误解,愚蠢的我><是的,你从类本身获得函数指针,并将其用于实例。误解来自于我对模板成员函数的错误概念。我试图(对自己)演示所有实例都具有所有重载,指向实例“概念上”不具有的函数。
struct Foo
{
void f<int>(int t) {};
void f<char>(char t) {};
void f<float>(float t) {};
...
/// all the other uses of f with different types, anywhere in your code.
};
struct Foo
{
void f(int);
void f(double);
};
// ...
Foo foo1, foo2;
foo1.f(3);
foo2.f(3.0);