具有模板化成员函数的类,是同一个类
Class with templated member function, is the same class?
我对模板化成员函数有点困惑,假设我们有一些带有模板化成员函数的奇怪结构,如下所示:
struct Foo
{
template <typename T> void f(T t) {};
};
然后,我们将该结构存储到某个标准容器中:
std::vector<Foo> V;
V.push_back(Foo());
V.push_back(Foo());
V.push_back(Foo());
V.push_back(Foo());
接下来;让我们调用模板化成员函数的不同实例:
V.at(0).f<int>(1);
V.at(0).f<char>(2);
V.at(1).f<float>(3.4f);
V.at(2).f<double>(5.6);
V.at(3).f<long>(7);
最后,问题:
¿Foo 类的所有实例都来自同一个类? 答案似乎是肯定的,但是...第一个 Foo 实例末尾有两个 f 成员函数的重载:
[0] Foo::f(int t);
[0] Foo::f(char t);
另一方面,其他 Foo 实例似乎只有一个版本的 f 函数。因此,由于成员函数的差异,显然每个实例的基本类型是不同的。
[1] Foo::f(float t);
[2] Foo::f(double t);
[3] Foo::f(long t);
显然,我们只能从第一个Foo实例中获取Foo::f(int t)函数的地址,因为该函数只属于该实例;其他函数也是如此。
提前谢谢。
所有重载都是由 Foo::f
成员函数的编译器生成的,您可以将其视为手动编写了所有重载。
而是基于类的,类本身会得到所有模板实例化(就像在类的主体中编写了不同类型的所有重载一样,对于给定的类型 T)
所以在你的情况下:
struct Foo
{
template <typename T> void f(T t) {};
};
将成为(概念上)
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.
};
这是人们反对模板的原因之一,它被称为"代码膨胀"。
¿Foo 类的所有实例都来自同一个类? 答案似乎是肯定的
是的,所有实例都属于同一类型。
但。。。第一个 Foo 实例末尾有两个 f 成员函数的重载
重载是按类型,而不是按实例。该类型将包含所有重载,而不考虑实例化模板函数的对象。
显然,我们只能从第一个Foo实例中获取Foo::f(int t)函数的地址,因为该函数只属于该实例;其他函数也是如此。
它们由编译器实例化(编译为二进制代码),其中不是一个正确的问题(二进制文件除外)。成员函数的地址只能从类中获取,而不能从任何实例中获取,正如我已经提到的,成员函数是按类型获取的,而不是按类型的实例获取的。
所有Foo
实例都具有所有重载,并且它们都是同一类型Foo
因为本身不是模板类。
函数在编译时在目标代码中实例化。
让我们看一个不同的例子:
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
的方法,并且所有实例都具有相同的类型。
- 为什么std::async使用同一个线程运行函数
- 是否可以使用非常量指针调用非常量函数,以及当两个unique_ptrs指向同一个对象时程序的行为方式?
- 如何将不同的函数签名映射到同一个 std::map?
- 如果两个线程调用同一个函数,但函数中的所有变量都是局部变量,我还需要担心线程之间共享数据吗?
- 两个单链列表共享同一个节点和析构函数两次删除相同的内存
- 有可能在同一个字符序列上有一个类似函数的宏和一个类似对象的宏吗
- 当调用来自同一个重载的非常量版本成员函数时,可以删除常量限定符吗
- 如何在同一个主文件中转发声明类似模板函数的模板类
- 如何在同一个类中同时具有参数化构造函数和默认构造函数
- 具有模板化成员函数的类,是同一个类
- C++ 结构函数体调用另一个结构函数,同一个模块
- 类成员函数调用类友元函数(都是同一个类)可能
- 为什么要将类的线程函数设置为静态,以便在同一个类中可以访问
- C++内联函数的定义必须在同一个文件中
- 如果基类和派生类都需要使用同一个函数,回调函数应该去哪里?
- 为什么表达式 a() 和 (****&a)() 调用同一个函数?
- c++在同一个函数中返回字符串引用和传递字符串引用
- c++: Boost::asio:在同一个函数中等待异步处理程序
- 两个或多个std::线程如何操作同一个函数
- 将两个维度大小不同的矩阵传递给同一个函数