В C++ TemplateClass


Я написал (динамический) TemplateArray класса, для использования в качестве базового для библиотеки, я работаю, и я хотел бы обратную связь с любым из следующих:

  • Как код может быть улучшен (даже если это просто ваше субъективное мнение)?
  • Как код может быть более эффективным?
  • Как функции класса могут быть сделаны более интуитивно понятным и удобным (это работает, как вы ожидаете его)?

namespace TL
{

template<typename TemplateItem>
class TemplateArray
{

protected:

        TemplateItem *Array;
        SIZE_TYPE Size;

        void Clear(){Array = NULL; Size = 0;}

    public:

        const bool IsEmpty() const { return ((Array == NULL) && (Size == 0)); }
        const bool IsValid() const { return ((Array != NULL) && (Size != 0)); }

        const bool operator!() const {return IsEmpty();}
        operator const bool () const {return IsValid();}

        const SIZE_TYPE GetSize() const {return Size;}

        const bool SetSize(const SIZE_TYPE S)
        {
            ERRORCLASSFUNCTION(TemplateArray,SetSize,S < 1,RETURN_BOOL)
            if(!IsEmpty())
            {
                Close();
            }
            ERRORCLASSFUNCTION(TemplateArray,SetSize,!CREATEB(Array,S),RETURN_BOOL)
            Size = S;
            return true;
        }

        const bool CopyArray(const TemplateItem Arr[], const SIZE_TYPE S)
        {
            ERRORCLASSFUNCTION(TemplateArray,CopyArray,S < 1,RETURN_BOOL);
            ERRORCLASSFUNCTION(TemplateArray,CopyArray,S > Size,RETURN_BOOL);

            SIZE_TYPE Temp = 0;
            while(Temp < S)
            {
                Array[Temp] = Arr[Temp];
                Temp++;
            }
            return true;
        }

        const bool SetArray(const TemplateItem Arr[], const SIZE_TYPE S)
        {
            ERRORCLASSFUNCTION(TemplateArray,SetArray,S < 1,RETURN_BOOL)
            ERRORCLASSFUNCTION(TemplateArray,SetArray,!SetSize(S),RETURN_BOOL)
            SIZE_TYPE Temp = 0;
            while(Temp < S)
            {
                Array[Temp] = Arr[Temp];
                Temp++;
            }
            return true;
        }

        const bool SetArray(const TemplateArray &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,SetArray,!ItemCopy,RETURN_BOOL)
            ERRORCLASSFUNCTION(TemplateArray,SetArray,!SetArray(ItemCopy.Array,ItemCopy.Size),RETURN_BOOL)
            return true;
        }

        const bool SetArray(const std::vector<TemplateItem> &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,SetArray,ItemCopy.empty(),RETURN_BOOL)
            ERRORCLASSFUNCTION(TemplateArray,SetArray,!SetArray(&ItemCopy[0],ItemCopy.size()),RETURN_BOOL)
            return true;
        }

        TemplateItem * const GetArray() { return Array; }
        const TemplateItem * const GetArray() const { return Array; }

        void TransferFrom(TemplateArray &ItemCopy)
        {
            Close();
            Array = ItemCopy.Array;
            Size = ItemCopy.Size;
            ItemCopy.Array = NULL;
            ItemCopy.Size = 0;
        }

        const bool Reverse()
        {
            ERRORCLASSFUNCTION(TemplateArray,Reverse,!IsValid(),RETURN_BOOL)
            TemplateArray<TemplateItem> Temp;
            ERRORCLASSFUNCTION(TemplateArray,Reverse,!Temp.SetSize(Size),RETURN_BOOL)
            TemplateItem *C_Ptr = Array+(Size-1), *C_Ptr_2 = Temp.GetArray();

            while(C_Ptr != Array)
            {
                *C_Ptr_2 = *C_Ptr;
                C_Ptr--; C_Ptr_2++;
            }
            *C_Ptr_2 = *C_Ptr;
            TransferFrom(Temp);
            return true;
        }

        const bool Compare(const TemplateItem Arr[], const SIZE_TYPE S)
        {
            if(!IsValid())
            {
                return false;
            }

            ERRORCLASSFUNCTION(TemplateArray,Compare,S < 1,RETURN_BOOL)
            SIZE_TYPE Temp = 0;

            while(Temp < S)
            {
                if(Array[Temp] != Arr[Temp]){return false;}
                Temp++;
            }

            return true;
        }

        const bool Compare(const TemplateArray &ItemCopy)
        {
            if(Size != ItemCopy.Size)
            {
                return false;
            }

            if(IsEmpty())
            {
                return true;
            }

            return Compare(ItemCopy.Array,ItemCopy.Size);
        }

        const bool Compare(const std::vector<TemplateItem> &ItemCopy)
        {
            if(ItemCopy.size() != Size)
            {
                return false;
            }

            if(ItemCopy.empty())
            {
                return true;
            }

            return Compare(&ItemCopy[0],ItemCopy.size());
        }

        const bool Append(const TemplateItem Data[], const SIZE_TYPE S)
        {
            ERRORCLASSFUNCTION(TemplateArray,Append,Data == NULL,RETURN_BOOL)
            ERRORCLASSFUNCTION(TemplateArray,Append,S < 1,RETURN_BOOL)
            TemplateArray<TemplateItem> Temp;
            ERRORCLASSFUNCTION(TemplateArray,Append,!Temp.SetSize(Size+S),RETURN_BOOL)
            SIZE_TYPE Temp2 = 0;
            while(Temp2 < Size)
            {
                Temp.Array[Temp2] = Array[Temp2];
                Temp2++;
            }

            Temp2 = 0;
            while(Temp2 < S)
            {
                Temp.Array[Temp2+Size] = Data[Temp2];
                Temp2++;
            }
            TransferFrom(Temp);
            return true;
        }

        //Tested
        const bool Append(const TemplateArray &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,Append,!ItemCopy.IsValid(),RETURN_BOOL)
            return Append(ItemCopy.GetArray(),ItemCopy.GetSize());
        }

        const bool Append(const std::vector<TemplateItem> &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,Append,ItemCopy.empty(),RETURN_BOOL)
            ERRORCLASSFUNCTION(TemplateArray,Append,!Append(&ItemCopy[0],ItemCopy.size()),RETURN_BOOL)
            return true;
        }

        const bool Append(const TemplateItem &ItemCopy)
        {
            return Append(&ItemCopy,1);
        }

        const bool Remove(const TemplateItem Data[], const SIZE_TYPE S)
        {
            ERRORCLASSFUNCTION(TemplateArray,Append,Data == NULL,RETURN_BOOL)
            ERRORCLASSFUNCTION(TemplateArray,Remove,S < 1,RETURN_BOOL)
            if(!IsValid()){return false;}
            if(S > Size){return false;}

            SIZE_TYPE Temp = 0, Temp2 = 0;

            do
            {
                Temp2 = 0;
                while(Temp < Size)
                {
                    if(Array[Temp] == Data[Temp2])
                    {
                        break;
                    }
                    Temp++;
                }

                while(Temp < Size)
                {
                    if(Array[Temp] != Data[Temp2])
                    {
                        break;
                    }

                    Temp++; Temp2++;

                    if(Temp2 == S)
                    {
                        break;
                    }
                }

                if(Temp2 == S)
                {
                    TemplateArray<TemplateItem> DataTemp;

                    ERRORCLASSFUNCTION(TemplateArray,operator-=,!DataTemp.SetSize(Size-S),RETURN_BOOL)
                    Temp2 = Temp - S;
                    Temp = 0;

                    while(Temp < Temp2)
                    {
                        DataTemp.Array[Temp] = Array[Temp];
                        Temp++;
                    }

                    Temp2 += S;

                    while(Temp2 < Size)
                    {
                        DataTemp.Array[Temp] = Array[Temp2];
                        Temp++; Temp2++;
                    }

                    TransferFrom(DataTemp);
                    return *this;
                }

            }while(Temp < Size);

            return *this;
        }

        const bool Remove(const std::vector<TemplateArray> &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,Remove,ItemCopy.empty(),RETURN_BOOL)
            ERRORCLASSFUNCTION(TemplateArray,Remove,!Remove(&ItemCopy[0],ItemCopy.size()),RETURN_BOOL)
            return true;
        }

        const bool Remove(const TemplateArray &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,Remove,!IsValid(),RETURN_BOOL)
            ERRORCLASSFUNCTION(TemplateArray,Remove,!Remove(ItemCopy.Array,ItemCopy.Size),RETURN_BOOL)
            return *this;
        }

        const bool Remove(const TemplateItem &ItemCopy)
        {
            return Remove(&ItemCopy,1);
        }

        void Reset()
        {
            if(Array != NULL)
            {
                DELETEB(Array);
            }
            Open();
        }
        void Open(){ Clear(); }
        void Close()
        {
            if(Array != NULL)
            {
                DELETEB(Array);
            }
            Clear();
        }

        //Tested
        TemplateArray(){Open();}

        ~TemplateArray(){Close();}

        //Tested
        TemplateArray(const TemplateItem Data[], const SIZE_TYPE S)
        {
            Open();
            ERRORCLASSFUNCTION(TemplateArray,TemplateArray,!SetArray(Data,S),)
        }

        //Tested
        TemplateArray(const TemplateArray &ItemCopy)
        {
            Open();
            ERRORCLASSFUNCTION(TemplateArray,TemplateArray,!SetArray(ItemCopy),)
        }

        TemplateArray(const std::vector<TemplateItem> &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,TemplateArray,!SetArray(ItemCopy),RETURN_VOID)
        }

        operator const SIZE_TYPE () const {return Size;}

        operator const std::vector<TemplateItem> () const
        {
            std::vector<TemplateItem> Temp;
            if(!IsValid())
            {
                return Temp;
            }

            try
            {
                Temp.resize(Size);
            }
            catch(...)
            {
                std::vector<TemplateItem> Temp2;
                ERRORCLASSFUNCTION(TemplateArray,std::vector,true,return Temp2;)
            }

            SIZE_TYPE Temp2 = 0;

            while(Temp2 < Size)
            {
                Temp[Temp2] = Array[Temp2];
                Temp2++;
            }

            return Temp;
        }

        const bool operator!=(const TemplateArray &ItemCopy){return !((*this) == ItemCopy);}
        const bool operator==(const TemplateArray &ItemCopy)
        {
            return Compare(ItemCopy);
        }

        const bool operator==(const std::vector<TemplateItem> &ItemCopy)
        {
            return Compare(ItemCopy);
        }

        TemplateArray &operator+=(const TemplateItem &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,operator+=,!Append(ItemCopy),RETURN_THIS)
            return *this;
        }

        //Tested
        TemplateArray &operator+=(const TemplateArray &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,operator+=,!Append(ItemCopy),RETURN_THIS)
            return *this;
        }

        //Tested
        TemplateArray &operator+=(const std::vector<TemplateItem> &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,operator+=,!Append(ItemCopy),RETURN_THIS)
            return *this;
        }

        TemplateArray &operator-=(const TemplateItem &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,operator-=,!Remove(ItemCopy),RETURN_THIS)
            return *this;
        }

        TemplateArray &operator-=(const std::vector<TemplateItem> &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,operator-=,!Remove(ItemCopy),RETURN_THIS)
            return *this;
        }

        TemplateArray &operator-=(const TemplateArray &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,operator-=,!Remove(ItemCopy),RETURN_THIS)
            return *this;
        }

        TemplateArray &operator=(const std::vector<TemplateItem> &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,operator=,!SetArray(ItemCopy),RETURN_THIS)
            return *this;
        }

        TemplateArray &operator=(const TemplateArray &ItemCopy)
        {
            ERRORCLASSFUNCTION(TemplateArray,operator=,!SetArray(ItemCopy),RETURN_THIS)
            return *this;
        }

        TemplateItem &operator[](const SIZE_TYPE S){ return Array[S]; }
        const TemplateItem &operator[](const SIZE_TYPE S) const { return Array[S]; }
};

}

Рабочий пример вы можете вставить непосредственно в ваш компилятор также доступна здесь.

Класс должен поддерживать следующие:

Чтобы минимизировать время отслеживания ошибок:

  • Голосовые сообщения об ошибках.
  • Отслеживаемые сообщения об ошибках.
  • Предохранители (выйти на первый отношение к проблеме).
  • Функции, которые в первую очередь возвращать bool и там, где это возможно.

Для совместимости с другими классами:

  • Вернуться и принять стандартных типов данных (в данном случае, СТД::вектор).

Класс должен поддерживать следующие требования:

  • Пользователя-дружелюбность. Пользователь не должен думать, когда с помощью класса.
  • Совместимость с будущим, потенциально неизвестных классов и подклассов.

Не обращайте внимания на макро, использования printf и то функции внутри класса. Это просто мои личные предпочтения. Пожалуйста, не предполагая, что через СТД::стринг/СТД::вектор (это очень старый стереотип, сейчас), как стандартные классы являются универсальными и не имеют определенных функций кастомный класс может (т. е. типа bool, вернувшись, ошибка-отчеты/трассировки функции), хотя также совместимость с такими классами.



324
5
задан 17 октября 2011 в 03:10 Источник Поделиться
Комментарии
2 ответа


Как код может быть улучшен (даже если это просто ваше субъективное мнение)?

Замените макросы с читаемым кодом.
Они делают его гораздо труднее читать и понимать, чем он должен быть.

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

Это нарушает свое правило пользователя. Пользователь не должен думать, когда с помощью класса. Теперь они сами должны думать. О дерьмо, что последняя операция просто потерял все свои данные я могу;т даже дамп моем нынешнем состоянии для отладки.

Вам не кажется, проверить задания самостоятельно (не то, что я вижу, я могу ошибаться, но код очень трудно читать). Таким образом вы будете разбивать как удалить массив копировании (себя), а затем прочитать Из теперь уже мертвого проживания illiciting неопределенному поведению.


Как код может быть более эффективным?

Для этого потребуется много времени.
Но, похоже, вы проделали основную работу все.

Это может улучшить использование метода своп, который может быть полезен в многих ситуациях и реализацию по умолчанию своп-это не очень эффективно для любого контейнера.

Вы не повторно использовать массив. Вы всегда удалить и выделить. Это может быть очень эффективным. Это может быть лучше, чтобы проверить, если массив копируются-за этого меньше, и если так повторно использовать массив только переместить/скопировать элементы в этот массив.

Вы не предварительно выделить память для возможного расширения в ближайшем будущем и таким образом попадают в ловушку, удаления и перераспределения массива для каждого толчка на заднюю неважно, насколько он большой.


Как функции класса могут быть сделаны более интуитивно понятным и удобным (это работает, как вы ожидаете его)?

Это где ваш класс-это ужасно. Это в основном самый недружелюбный класс-контейнер, я видел и может не быть использована с любой из стандартных алгоритмов, что делает его практически непригодным для использования.


Как правило, все-круглый дружеский совет верстальщика не эксперт.


  • Избавиться от макросов, заменив их функции.

  • Реализации итераторов. (так что вы можете использовать стандартные алгоритмы)

  • Обеспечить лучшую защиту для вашего пользователя.

    • Операции, которые не должны оставить объект без изменений.


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

6
ответ дан 17 октября 2011 в 05:10 Источник Поделиться

Все ваши методы имеют соответствующие функциональные возможности с СТД::вектор. Я предлагаю вам написать свой класс как обертка вокруг СТД::вектор.

   template<typename TemplateItem>
class TemplateArray
{
public:
// std::vector::empty
const bool IsEmpty() const { return ((Array == NULL) && (Size == 0)); }

// unnecessary
const bool IsValid() const { return ((Array != NULL) && (Size != 0)); }
const bool operator!() const {return IsEmpty();}
operator const bool () const {return IsValid();}

// std::vector::size
const SIZE_TYPE GetSize() const {return Size;}

// std::vector::resize
const bool SetSize(const SIZE_TYPE S)

// std::copy
const bool CopyArray(const TemplateItem Arr[], const SIZE_TYPE S)
const bool SetArray(const TemplateItem Arr[], const SIZE_TYPE S)
const bool SetArray(const TemplateArray &ItemCopy)
const bool SetArray(const std::vector<TemplateItem> &ItemCopy)
TemplateItem * const GetArray() { return Array; }
const TemplateItem * const GetArray() const { return Array; }

// move constructor
void TransferFrom(TemplateArray &ItemCopy)

// std::reverse
const bool Reverse()

// std::vector::operator==
const bool Compare(const TemplateItem Arr[], const SIZE_TYPE S)
const bool Compare(const TemplateArray &ItemCopy)
const bool Compare(const std::vector<TemplateItem> &ItemCopy)

// std::vector::push_back
const bool Append(const TemplateItem Data[], const SIZE_TYPE S)
const bool Append(const TemplateArray &ItemCopy)
const bool Append(const std::vector<TemplateItem> &ItemCopy)
const bool Append(const TemplateItem &ItemCopy)

// std::vector::erase + std::remove.
const bool Remove(const TemplateItem Data[], const SIZE_TYPE S)
const bool Remove(const std::vector<TemplateArray> &ItemCopy)
const bool Remove(const TemplateArray &ItemCopy)
const bool Remove(const TemplateItem &ItemCopy)

// std::vector::clear
void Clear()
void Reset()

// A bit wierd, but i guess you want something like std::vector::clear + std::vector::shrink_to_fit
void Open()
void Close()

// Nice to have i guess, std::vector::push_back
TemplateArray &operator+=(const TemplateItem &ItemCopy)

// std::vector::operator[]
TemplateItem &operator[](const SIZE_TYPE S){ return Array[S]; }
const TemplateItem &operator[](const SIZE_TYPE S) const { return Array[S]; }
};

1
ответ дан 17 октября 2011 в 04:10 Источник Поделиться