C ++ новое наследование операторов и встроенные структуры данных - PullRequest
1 голос
/ 07 октября 2010

У меня есть система (C ++), в которой есть много классов, которые имеют требования к переменной памяти (памяти). В большинстве этих случаев размер требуемого хранилища известен при создании объекта и устанавливается на весь срок службы объекта.

Я использую это, например, для создания объекта «String» с полем счетчика, за которым непосредственно следуют реальные символы, встроенные в объект.

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; }

Теперь я мог бы просто продублировать оператор new для каждого из классов (String, Node, ...), но это наполовину проиграет цель рефакторинга.

Есть ли простое решение для этого? Я хотел бы поддерживать данные встроенными в остальную часть класса (чтобы избежать разыменования и выделения кучи), а также избежать нестандартных расширений (таких как массивы нулевого размера в конце классов). В то же время я хотел бы уменьшить дублирование.

1 Ответ

1 голос
/ 07 октября 2010

Вы использовали

using Expando::new

в своем производном операторе new?Например:

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

В противном случае, если вы не возражаете против моего мнения, я думаю, что ваша реализация вашего класса String слишком далека.У вас есть элемент count, но нет фактического элемента данных указателя, который бы указывал на массив того, что будет содержать вашу строку.Разговор о странной реализации.Это просто напрашивается на неприятности у разработчика по техобслуживанию через несколько лет, когда они почесывают голову и говорят: «Чего?»

...