我有一个(C ++)系统,它有许多具有可变存储(内存)要求的类。在大多数情况下,所需存储的大小在创建对象时是已知的,并且在对象的生命周期内是固定的。
例如,我使用它来创建一个“String”对象,该对象具有一个count字段,后面跟着实际字符,与对象内联。
class String {
public:
size_t count;
String(size_t count, const char* text) : count(count) {/*...*/}
inline char& at(size_t index) {
return *(reinterpret_cast<char*>(this + 1) + index);
}
void* operator new (size_t size, size_t count) {
return new char[size + count * sizeof(char)];
}
};
class Node {
public:
size_t count;
Node(size_t count, ...) : count(count) {/*...*/}
inline Node*& at(size_t index) {
return *(reinterpret_cast<Node**>(this + 1) + index);
}
void* operator new (size_t size, size_t count) {
return new char[size + count * sizeof(Node*)];
}
};
// ... and several more like this
我试图通过将这种“内联数组”行为分解为一个公共基类来减少这种代码重复:
template<class T>
class Expando {
size_t count;
Expando(size_t count) : count(count) {}
inline T& at(size_t index) {
return *(reinterpret_cast<T*>(this + 1) + index);
}
void* operator new (size_t size, size_t count) {
return new char[size + count * sizeof(T)];
}
};
然而,当我从这个类继承时:
class String : public Expando<char> {/*...*/}
然后去创建一个新的字符串:
String* str = new (4) String(4, "test");
GCC尝试使用全局重载的新运算符,而不是Expando中的运算符:
inline void* operator new (size_t size, void* mem) { return mem; }
现在,我可以为每个类(String,Node,...)复制new运算符,但这会使重构的目的失败一半。
有一个简单的解决方案吗?我想将数据与类的其余部分保持内联(以避免额外的解除引用和堆分配),以及避免非标准扩展(例如类末尾的零大小数组)。与此同时,我想减少重复。
答案 0 :(得分:1)
using Expando::new
你的派生类new运算符中的?例如:
void* operator new (....)
{
using Expando::new;
....
}
否则,如果你不介意我的意见,我认为你的String类的实现是偏离基础的。你有一个count成员,但没有实际的指针数据成员指向一个包含你的字符串的数组。谈论一个奇怪的实现。这只是在维护开发人员几年后遇到麻烦,因为他们划伤头脑并走了:“Whaaat?”