C ++新的运算符继承和内联数据结构

时间:2010-10-07 04:29:20

标签: c++ inheritance new-operator

我有一个(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运算符,但这会使重构的目的失败一半。

有一个简单的解决方案吗?我想将数据与类的其余部分保持内联(以避免额外的解除引用和堆分配),以及避免非标准扩展(例如类末尾的零大小数组)。与此同时,我想减少重复。

1 个答案:

答案 0 :(得分:1)

你使用过

吗?
using Expando::new
你的派生类new运算符中的

?例如:

void* operator new (....)
{
    using Expando::new;
    ....
}

否则,如果你不介意我的意见,我认为你的String类的实现是偏离基础的。你有一个count成员,但没有实际的指针数据成员指向一个包含你的字符串的数组。谈论一个奇怪的实现。这只是在维护开发人员几年后遇到麻烦,因为他们划伤头脑并走了:“Whaaat?”