我有一个模板化的容器类,类似于这个玩具代码:
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类型的对象,等等,所有Just Works(tm)都没有任何需要的东西
然而,有一件令我困扰的事情是_defaultItem成员变量的存在,这只是为了让GetFirstItemWithDefault()能够在容器为空时返回有效的引用。反对意见是,如果我声明N MyVector对象,这意味着_defaultItem的N个副本也将出现在RAM中 - 即使它们都是相同且只读的,因此实际上只需要其中一个过程,而不是每个MyVector。因此,显而易见的解决方案是使_defaultItem成为静态....但AFAICT带有成本:如果我这样做,任何旧代码都不再可能只需#include“MyVector.h”然后...现在用户必须确保在他的一个.cpp文件中为该静态变量声明存储,这是(a)一个痛苦的屁股,(b)意味着代码的用户已经要了解班级内部实施的细节。由于_defaultItem是一个私有成员变量,因此该类的用户不应该考虑它,甚至不应该意识到它存在,更不用说知道他需要为它声明存储。 (如果两个独立的代码段都为它声明了存储,每个不知道另一个代码都做了同样的事情呢?这不会导致重复符号链接器错误吗?)
因此,我的问题是:有没有办法告诉C ++为这个静态成员变量自动提供一个唯一的存储空间(每个实例化的MyVector类型),以便MyVector的用户不必知道它? (请注意,对于MyVector&lt; ...&gt;的所有可能实例化,它都需要是自动的,而不只是针对一些常见情况)
答案 0 :(得分:8)
为什么不将该默认项目设为静态本地函数?
const ItemType & GetFirstItemWithDefault() const
{
static const ItemType _default;
return (_numItems > 0) ? _items[0] : _default;
}
如果你想再次检查某个其他功能中的默认项目,这可能不是你想要的,但为此你可以把它放在一个单独的函数中(也可能是静态的):
static const ItemType& GetDefault() const
{
static const ItemType _default;
return _default;
}
当您需要访问默认项目时调用该函数。
那就是说,我认为有一个默认项目并不是很好。 std::vector
也没有它,也不需要它。只需告诉用户检查向量是否为empty
并完成。隐藏静态的一个问题是,您不知道ItemType
。它可能是一个吃掉大量资源的类,你只是做了另一个例子!也许重新考虑该类的设计,然后切换到std::vector
。 :)
答案 1 :(得分:3)
如果它是模板,编译器将为您完成魔术。只需将静态成员放在头文件中,编译器就会看到它只是实例化了一次。
template <class ItemType>
class MyVector
{
public:
//...
private:
static const ItemType _defaultItem;
};
template <class ItemType>
const ItemType MyVector<ItemType>::_defaultItem;
答案 2 :(得分:3)
所以,显而易见的解决方案是制作 _defaultItem static ....但AFAICT带有成本:如果我这样做, 任何旧的都不再可能 一段代码简单地#include “MyArray.h”并且......现在用户已经拥有了 一定要申报存储 他的一个.cpp中的静态变量 文件,这是(a)痛苦
否即可。这种担心是出于担忧。在template
中,您可以(必须)在同一文件中声明static
变量。
template <class ItemType> class MyVector
{
const ItemType _defaultItem;
};
template <class ItemType>
const ItemType MyVector<ItemType>::_defaultItem; // ok (no multiple symbols)
另请注意,只有在调用static
时才会实例化此GetFirstItemWithDefault()
成员。所以不要担心冗余分配。
唯一担心的是为所有ItemType
提供默认构造函数,因为static
对象通常会依赖于默认构造函数(您必须关注它) , 我猜)。就是这样。