看看以下代码:
#include <iostream>
template <typename T>
class Foo
{
public:
static T bar;
};
template <typename T> typename T Foo<T>::bar;
int main() {
std::cout << "Foo<int>::bar : " << &Foo<int>::bar << std::endl;
std::cout << "Foo<double>::bar : " << &Foo<double>::bar << std::endl;
return 0;
}
这将打印出2个不同的地址。我理解为什么在这种情况下,bar
属于T
类型,因此Foo<T>
中不同T的实例会为您提供不同的静态成员。但是,如果我们将bar
更改为我们已知道的类型(例如static int bar
)此still happens。
为什么会这样?为什么不重复使用bar
进行多个模板实例化?在不同的实例中,我怎么能只获得1 bar
个对象?
答案 0 :(得分:11)
这里没有什么令人惊讶的事情。
template <typename T>
class Foo
{
//...
};
不是一个类,它是一个标记类的模板。这意味着Foo<A>
与Foo<B>
完全不同。因此,所有静态成员对于不同的实例化类是唯一的 - 并且类模板相同的事实在此上下文中没有相关性,因为它毕竟是模板,实例化类的蓝图。
如果您希望所有不同类型的Foo
共享一个公共状态,那么您可以让它们从同一个基类继承并将公共信息放在那里。这是一个非常简单的例子:
struct Foo_Base
{
static int bar;
};
int Foo_Base::bar = 10;
template<typename T>
struct Foo : Foo_Base {};
int main()
{
Foo<int> foo_i;
Foo<double> foo_d;
std::cout << foo_i.bar << "\n";
foo_i.bar += 10;
std::cout << foo_d.bar;
}
输出:
10
20
答案 1 :(得分:9)
从标准,$ 14.7 / 6模板实例化和专业化[temp.spec]
从模板实例化的每个类模板特化都有自己的任何静态成员副本。
Foo<double>
和bar
是不相关的类,即使它们是从同一模板实例化的,并且它们将拥有自己的静态成员int
,即使它们的类型是相同(例如public $file_ext_tolower = TRUE;
}。
答案 2 :(得分:0)
Foo<int>::bar
和Foo<double>::bar
是两个不同的全局(静态可访问的类级别)变量。他们不一样。请考虑以下代码:
template <typename T>
class Foo
{
public:
static T var1;
static int var2;
};
您认为var2
的相对位置是什么(假设编译器在var2
之后放置var1
)?在一种情况下,它可能相对只提前1个字节(foo<char>
),但在其他数据类型的情况下提前8个字节。