我的模板类中是否可以有一个静态成员变量,而类的用户不必知道它?
我有一个模板化容器类,类似于这个玩具代码:
template <class ItemType> class MyVector
{
public:
MyVector() : _numItems(0), _items(NULL) {/* empty */}
/** Returns a reference to the first item in our array,
* or a default-constructed item if the array is empty.
*/
const ItemType & GetFirstItemWithDefault() const
{
return (_numItems > 0) ? _items[0] : _defaultItem;
}
[other methods omitted because they aren't relevant]
private:
int _numItems; // how many valid items (_items) points to
ItemType * _items; // demand-allocated
const ItemType _defaultItem;
};
这个类使用起来非常方便——任何代码都可以#include“MyVector.h”,然后开始声明 MyVector 和 MyVector 等类型的对象,等等可以正常工作(tm),不需要任何麻烦。
然而,让我困扰的一件事是 _defaultItem 成员变量的存在,它的存在只是为了让 GetFirstItemWithDefault() 在容器为空时返回有效引用。反对意见是,如果我声明 N 个 MyVector 对象,这意味着 RAM 中也会存在 _defaultItem 的 N 个副本 --- 即使它们都是相同的且只读,因此每个对象实际上只需要其中一个进程,不是每个 MyVector 都有一个进程。
因此,显而易见的解决方案是使 _defaultItem 静态......但 AFAICT 会带来成本:如果我这样做,任何旧代码都不再可能简单地#include“MyVector.h”并继续。 .. 现在,用户必须确保在他的一个 .cpp 文件中声明该静态变量的存储,这 (a) 是一件令人头疼的事情,(b) 意味着代码的用户必须意识到这一点类的内部实现的细节。由于 _defaultItem 是一个私有成员变量,所以该类的用户不必考虑它,甚至不必意识到它的存在,更不用说知道他需要为其声明存储空间。 (如果两个单独的代码都声明了它的存储空间,而每个代码都不知道对方做了同样的事情怎么办?这不会导致重复符号链接器错误吗?)
因此,我的问题是:有没有办法告诉 C++ 自动为这个静态成员变量提供一个唯一的存储(每个 MyVector 的实例化类型),以便 MyVector 的用户不必知道它? (请注意,对于 MyVector<...> 的所有可能实例化,它需要是自动的,而不仅仅是对于一些常见情况)
I have a templated container class, something like this toy code:
template <class ItemType> class MyVector
{
public:
MyVector() : _numItems(0), _items(NULL) {/* empty */}
/** Returns a reference to the first item in our array,
* or a default-constructed item if the array is empty.
*/
const ItemType & GetFirstItemWithDefault() const
{
return (_numItems > 0) ? _items[0] : _defaultItem;
}
[other methods omitted because they aren't relevant]
private:
int _numItems; // how many valid items (_items) points to
ItemType * _items; // demand-allocated
const ItemType _defaultItem;
};
This class is really convenient to use -- any code can just #include "MyVector.h" and then start declaring objects of type MyVector and MyVector and so on, and it all Just Works (tm) without any futzing around required.
One thing that kind of bothers me, however, is the presence of the _defaultItem member variable, which is there solely to give GetFirstItemWithDefault() the ability to return a valid reference when the container is empty. The objection is that if I declare N MyVector objects, that means N copies of _defaultItem will be present in RAM as well --- even though they are all identical and read-only, and so there really only needs to be one of them per process, not one per MyVector.
So, the obvious solution is to make _defaultItem static .... but AFAICT that comes with a cost: if I do that, it is no longer possible for any old piece of code to simply #include "MyVector.h" and go... now the user has to be sure to declare storage for that static variable in one of his .cpp files, which is (a) a pain in the butt, and (b) means that the user of the code has to be aware of the details of the internal implementation of the class. Since _defaultItem is a private member variable, the user of the class shouldn't have to think about it or even realize it exists, let alone know that he needs to declare storage for it. (and what if two separate pieces of code both declare storage for it, each not knowing the other has done the same thing? Wouldn't that cause a duplicate-symbol linker error?)
Therefore, my question is: is there any way to tell C++ to automatically provide one unique storage (per instantiated type of MyVector) for this static member variable, so that users of MyVector don't have to know about it? (Note that it would need to be automatic for all possible instantiations of MyVector<...>, not just for a few common cases)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
为什么不将该默认项设为该函数的静态本地项?
如果您想再次检查其他函数中的默认项,这可能不是您想要的,但为此您也可以将其放入单独的函数中(本身可能是静态的):
并在需要时调用该函数访问默认项目。
也就是说,我认为拥有默认项目并不是很好。
std::vector
也没有它并且不需要它。只需告诉用户检查向量是否为空即可完成。隐藏静态的一个问题是您不知道ItemType
。它可能是一个消耗大量资源的类,而您刚刚创建了另一个实例!也许重新考虑该类的设计,然后切换到 std::vector 。 :)Why not make that default item static local to the function?
This may not be what you want if you want to check against the default item in some other function again, but for that you can just put it in a seperate function aswell (that may be static itself):
And call that function when you need to access the default item.
That said, I think having a default item isn't really nice.
std::vector
also doesn't have it and doesn't need it. Just tell the user to check if the vector isempty
and be done. One problem with hidden statics is, that you don't knowItemType
. It could be a class that eats tons of resources and you just made another instance of that! Maybe rethink that class' design and after that, switch to astd::vector
. :)如果它是模板,编译器将为您发挥作用。只需将静态成员放在标头中,编译器就会发现它仅被实例化一次。
If it is a template, the compiler will do the magic for you. Just put the static member in the header, and the compiler will see to that it is just instantiated once.
不。这种恐惧是出于担忧。在
template
中,您可以(必须)在同一文件中声明static
变量。另请注意,仅当调用
GetFirstItemWithDefault()
时,才会实例化此static
成员。所以也不用担心冗余分配。唯一需要担心的是为所有
ItemType
提供默认构造函数,因为static
对象通常会依赖于默认构造函数(您必须我想已经在乎了)。就是这样。No. This fear is out of concern. In
template
s you can (must) declare thestatic
variable in the same file.Also, note that this
static
member will be instantiated only ifGetFirstItemWithDefault()
is called. So don't worry about redundant allocation also.The only thing worry is to provide default constructor to all the
ItemType
as thestatic
object will generically rely on the default constructor (which you must be caring about already, I guess). That's it.