【发布时间】:2012-08-23 13:21:01
【问题描述】:
模板类的所有静态成员都为它的每个实例复制。如果我想要一个对所有实例只存在一次的静态成员,我该怎么办?在类模板之外使用普通的静态字段?会工作,但似乎不优雅,因为没有更多与模板类的关联。有没有办法以某种方式将这种独特的静态成员与模板类相关联?
【问题讨论】:
标签: c++ templates static-members
模板类的所有静态成员都为它的每个实例复制。如果我想要一个对所有实例只存在一次的静态成员,我该怎么办?在类模板之外使用普通的静态字段?会工作,但似乎不优雅,因为没有更多与模板类的关联。有没有办法以某种方式将这种独特的静态成员与模板类相关联?
【问题讨论】:
标签: c++ templates static-members
没有;每个模板类都是一个完全独立的对象。
你可以做的是用静态成员创建一个共同的祖先类:
class Parent
{
public:
static int commonStatic;
};
template <typename T>
class MyTempl : public Parent
{
static int nonSharedStatic;
};
【讨论】:
basic_ios<CharT, CharTraitsT> 是一个完美的例子,说明如何从一个通用的非模板基 (std::ios_base) 继承是有意义的。他们主要共享所有格式标志常量。用户不在乎他们也可以做std::ios_base::hex。他们可以做到ostream::hex,因为这是他们在使用cout 时所面临的课程。
一个模板类的所有静态成员都为它的每个实例复制。
不。每个专业化都有不同的静态,但不同的专业化是不同的类。别搞错了,vector<int> 和 vector<char> 是完全分开的。把它想象成写IntVector和CharVector。
编辑:不要为此使用继承。仅仅为了共享静态成员而引入基类绝对是错误的做法。
如果您希望在不同的班级之间共享内容,请像往常一样进行。在第三个类中包装一些静态变量,就是这样。
【讨论】:
为模板类定义一些基类。在这个基类中包含所有常见的成员:
class ExampleBase {
public:
static int foo;
};
int ExampleBase::foo = 0;
template <class A>
class Example : private ExampleBase {
public:
static void setFoo(int f) { foo = f; }
static int getFoo() { return foo; }
};
那么每个 Example 实例都有共同的静态成员ExampleBase::foo:
int main() {
Example<int>::setFoo(7);
assert(Example<float>::getFoo() == 7);
};
【讨论】:
在某处放置一个全局变量。
类似这样的:
#include <iostream>
// header.hpp
extern int someValue;
template< typename T >
struct A
{
int foo() const
{
return someValue;
}
};
// source.cpp
int someValue = 5;
int main()
{
std::cout << A< float >().foo() << std::endl;
std::cout << A< int >().foo() << std::endl;
}
【讨论】:
在类模板之外使用普通的静态字段?
完全正确;只需将其放入模板声明之外的函数中即可。
如果真的想在这种情况下限制访问,你可以使用这样的东西:
class t_shared {
static int& Shared() {
static int s(0);
return s;
}
public:
template < typename T >
class t_template {
public:
void f() {
std::cout << ++Shared() << std::endl;
}
};
};
int main(int argc, const char* argv[]) {
t_shared::t_template<int>().f();
return 0;
}
【讨论】:
类模板在静态成员方面实际上与普通类有点不同。即使每个翻译单元都包含foo.hpp,以下内容也很好:
foo.hpp:
template <typename T> struct TmplFoo
{
static double d;
};
struct OrdFoo
{
static double e;
}
foo.cpp:
#include "foo.hpp"
double OrdFoo::e = -1.5;
请注意,我们从不需要单独定义TmplFoo<T>::d。链接器知道如何确定所有对TmplFoo<T>::d 的本地引用(对于给定的T)都指向同一个对象。
【讨论】: