C++模板实现,支持多维,安全数组的完整代码

简介: C++模板实现,支持多维,安全数组的完整代码

经过一番研究及测试,通过.需要的朋友可以参考.有以下特点:


完整重载了各必要操作符。

区分不同的类型,进行初始化。

为了验证,特别增加了测试代码。

可以支持多维操作.


 完整代码如下:


头文件

#ifndef __GH_SAFE_ARRAY_H__
#define __GH_SAFE_ARRAY_H__
/**
 * 如何解决memcpy/memset之类的问题?
 * 二维多维数组怎么支持?
 */
template <class TYPE>
class SafeArray
{
public:
    SafeArray();
    SafeArray(const int size);
    SafeArray(const int size, const char* pFile, const char* pFunction, const int nLine);
    ~SafeArray();
    void  init(const int size);
    void  init(const int size, const char* pFile, const char* pFunction, const int nLine);
    int   getSize();
    int   getCurrentOffset();
    bool  isStart();
    bool  isEnd();
    void  resetOffset();
    TYPE& operator[](const int i);
    SafeArray<TYPE>& operator+(const int i);
    SafeArray<TYPE>& operator-(const int i);
    TYPE* operator++(const int i);
    TYPE* operator--(const int i);
    TYPE* operator+=(const int i);
    TYPE* operator-=(const int i);
    //memcpy
    //memset
    //copy
    //clone
private:
    TYPE* m_pData;
    int   m_nSize;
    int   m_nCurrent;
    char* m_pFile;
    char* m_pFunction;
    int   m_nLine;
};
#endif



实现文件

/**
在C++面向对象程序设计中,有时候需要判断某个对象的类类型,那么可以有下列两种方法:
方法1:采用 typeid()函数进行判断:(缺点:当存在继承,并且子类指针赋值给父类指针时,此时判断的对象类型为父类型,而不是子类类型)
方法2:定义虚函数返回类类型
在运行时类型识别,最简单的办法就是所有的类(父类和子类)实现一个虚方法返回类名字,根据返回类名字再利用typeid()进行判断。如:
 */
template <typename T>
void test(T temp)
{
 //cout<<temp<<endl;
}
//判断两个类型是否一样
template<typename T1, typename T2>
struct is_same_type
{
    operator bool()
    {
        return false;
    }
};
template<typename T1>
struct is_same_type<T1, T1>
{
    operator bool()
    {
        return true;
    }
};
template <typename T> struct is_type_char\
                {    operator bool()    {    return false;   }};
template <>           struct is_type_char<char>\
                {    operator bool()    {    return true;    }};
template <typename T> struct is_type_int\
                {    operator bool()    {    return false;   }};
template <>           struct is_type_int<int>\
                {    operator bool()    {    return true;    }};
template <typename T> struct is_base_type
{
    operator bool()
    {
        return    is_type_char<T>()
               || is_type_int <T>();
    }
};
template <class TYPE>
SafeArray<TYPE>::SafeArray()
{
    init(0, __FILE__, __FUNCTION__, __LINE__);
}
template <class TYPE>
SafeArray<TYPE>::SafeArray(const int size)
{
    //new (this) SafeArray::SafeArray<TYPE>(m_nSize, __FILE__, __FUNCTION__, __LINE__);
    init(size, __FILE__, __FUNCTION__, __LINE__);
}
template <class TYPE>
SafeArray<TYPE>::SafeArray(const int size, const char* pFile, const char* pFunction, const int nLine)
{
    init(size, pFile, pFunction, nLine);
}
template <class TYPE>
void  SafeArray<TYPE>::init(const int size)
{
    init(size, __FILE__, __FUNCTION__, __LINE__);
}
template <class TYPE>
void  SafeArray<TYPE>::init(const int size, const char* pFile, const char* pFunction, const int nLine)
{
    m_nSize = size;
    m_pData = new TYPE[m_nSize];
    m_nCurrent = 0;
    if (is_base_type<TYPE>())
    {
        memset(m_pData, 0, sizeof(TYPE)*m_nSize);
    }
    this->m_pFile     = (char*)pFile;
    this->m_pFunction = (char*)pFunction;
    this->m_nLine     = nLine;
    //gh_memory_increase(this, m_pFile, m_pFunction, m_nLine, size);
}
template <class TYPE>
SafeArray<TYPE>::~SafeArray()
{
    if (m_pData != NULL)
    {
        delete[] (m_pData);
        m_pData = NULL;
        m_nSize = 0;
    }
    //gh_memory_decrease(this, m_pFile, m_pFunction, m_nLine);
}
template <class TYPE>
bool  SafeArray<TYPE>::isStart()
{
    return (m_nCurrent == 0);
}
template <class TYPE>
bool  SafeArray<TYPE>::isEnd()
{
    return (m_nCurrent+1 == m_nSize);
}
template <class TYPE>
int   SafeArray<TYPE>::getSize()
{
    return m_nSize;
}
template <class TYPE>
int   SafeArray<TYPE>::getCurrentOffset()
{
    return m_nCurrent;
}
template <class TYPE>
void  SafeArray<TYPE>::resetOffset()
{
    m_nCurrent = 0;
}
template <class TYPE>
TYPE& SafeArray<TYPE>::operator[](const int i)
{
    int pos = (m_nCurrent+i);
    if (pos >= m_nSize )
    {
        GH_LOG_ERROR("Out of Array Range! %d+%d > %d", m_nCurrent, i, m_nSize);
        // 返回第一个元素
        return m_pData[0];
    }
    return m_pData[pos];
}
template <class TYPE>
SafeArray<TYPE>& SafeArray<TYPE>::operator+(const int i)
{
    m_nCurrent += i;
    if (m_nCurrent + i >= m_nSize)
    {
        GH_LOG_ERROR("Out of Array Range! %d+%d > %d", (m_nCurrent-i), i, m_nSize);
        m_nCurrent = 0;
    }
    return (*this);
}
template <class TYPE>
SafeArray<TYPE>& SafeArray<TYPE>::operator-(const int i)
{
    m_nCurrent -= i;
    if (m_nCurrent < 0)
    {
        GH_LOG_ERROR("Out of Array Range! %d-%d < 0", (m_nCurrent+i), i);
        m_nCurrent = 0;
    }
    return (*this);
}
template <class TYPE>
TYPE* SafeArray<TYPE>::operator ++ (const int i)
{
    m_nCurrent ++;
    if (m_nCurrent >= m_nSize)
    {
        GH_LOG_ERROR("Out of Array Range! %d++ >= %d", (m_nCurrent-1), m_nSize);
        m_nCurrent = 0;
        return m_pData;
    }
    return m_pData+m_nCurrent;
}
template <class TYPE>
TYPE* SafeArray<TYPE>::operator -- (const int i)
{
    m_nCurrent --;
    if (m_nCurrent < 0)
    {
        GH_LOG_ERROR("Out of Array Range! %d-1 < 0", (m_nCurrent+1));
        m_nCurrent = 0;
        return m_pData;
    }
    return m_pData+m_nCurrent;
}
template <class TYPE>
TYPE* SafeArray<TYPE>::operator+=(const int i)
{
    m_nCurrent += i;
    if (m_nCurrent >= m_nSize)
    {
        GH_LOG_ERROR("Out of Array Range! %d+%d > %d", (m_nCurrent-i), i, m_nSize);
        m_nCurrent = 0;
        return m_pData;
    }
    return m_pData+m_nCurrent;
}
template <class TYPE>
TYPE* SafeArray<TYPE>::operator-=(const int i)
{
    m_nCurrent -= i;
    if (m_nCurrent < 0)
    {
        GH_LOG_ERROR("Out of Array Range! %d+%d < 0", (m_nCurrent+i), i);
        m_nCurrent = 0;
        return m_pData;
    }
    return m_pData+m_nCurrent;
}
#if 1
void testFor1d(SafeArray<int>& test1d)
{
    test1d.resetOffset();
    test1d ++;
    printf("++   %2d\n", test1d[0]);
    test1d --;
    printf("--   %2d\n", test1d[0]);
    test1d += 16;
    printf("+=16 %2d\n", test1d[0]);
    test1d -= 16;
    printf("-=16 %2d\n", test1d[0]);
    test1d = test1d + 10;
    printf(" +10 %2d\n", test1d[0]);
    test1d = test1d - 10;
    printf(" -10 %2d\n", test1d[0]);
}
int main(int argc, char** argv)
{
#if 0
    //OK
    SafeArray<int> test1d(32);
    for (int i=0; i<test1d.getSize(); i++)
    {
        test1d[i] = i;
    }
    testFor1d(test1d);
#endif
#if 0
    //OK
    SafeArray<SafeArray<int>> test2d(32);
    for (int i=0; i<test2d.getSize(); i++)
    {
        //显式初始化
        test2d[i].init(32);
        for (int j=0; j<test2d[i].getSize(); j++)
        {
            test2d[i][j] = i*100 + j;
        }
        testFor1d(test2d[i]);
    }
#endif
#if 1
    //OK
    SafeArray<SafeArray<int>*> test2d2(32);
    for (int i=0; i<test2d2.getSize(); i++)
    {
        //显式新建
        test2d2[i] = new SafeArray<int>(32);
        for (int j=0; j<test2d2[i]->getSize(); j++)
        {
            (*test2d2[i])[j] = i*100 + j;
        }
        testFor1d(*test2d2[i]);
    }
#endif
}
#endif


目录
相关文章
|
16天前
|
C++
C++ 语言异常处理实战:在编程潮流中坚守稳定,开启代码可靠之旅
【8月更文挑战第22天】C++的异常处理机制是确保程序稳定的关键特性。它允许程序在遇到错误时优雅地响应而非直接崩溃。通过`throw`抛出异常,并用`catch`捕获处理,可使程序控制流跳转至错误处理代码。例如,在进行除法运算或文件读取时,若发生除数为零或文件无法打开等错误,则可通过抛出异常并在调用处捕获来妥善处理这些情况。恰当使用异常处理能显著提升程序的健壮性和维护性。
33 2
|
10天前
|
编译器 C++
【C++】——初识模板
【C++】——初识模板
23 1
【C++】——初识模板
|
9天前
|
算法框架/工具 C++ Python
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
根据相机旋转矩阵求解三个轴的旋转角/欧拉角/姿态角 或 旋转矩阵与欧拉角(Euler Angles)之间的相互转换,以及python和C++代码实现
81 0
|
3天前
|
C++
C++(十一)对象数组
本文介绍了C++中对象数组的使用方法及其注意事项。通过示例展示了如何定义和初始化对象数组,并解释了栈对象数组与堆对象数组在初始化时的区别。重点强调了构造器设计时应考虑无参构造器的重要性,以及在需要进一步初始化的情况下采用二段式初始化策略的应用场景。
|
16天前
|
C++
拥抱C++面向对象编程,解锁软件开发新境界!从混乱到有序,你的代码也能成为高效能战士!
【8月更文挑战第22天】C++凭借其强大的面向对象编程(OOP)能力,在构建复杂软件系统时不可或缺。OOP通过封装数据和操作这些数据的方法于对象中,提升了代码的模块化、重用性和可扩展性。非OOP方式(过程化编程)下,数据与处理逻辑分离,导致维护困难。而OOP将学生信息及其操作整合到`Student`类中,增强代码的可读性和可维护性。通过示例对比,可以看出OOP使C++代码结构更清晰,特别是在大型项目中,能有效提高开发效率和软件质量。
19 1
|
9天前
|
C++ 索引
C++数组、vector求最大值最小值及其下标
C++数组、vector求最大值最小值及其下标
32 0
|
10天前
|
C++
C++代码来计算一个点围绕另一个点旋转45度后的坐标
C++代码来计算一个点围绕另一个点旋转45度后的坐标
28 0
|
10天前
|
C++
Resharper c++ 使用Enter自动补全代码
Resharper c++ 使用Enter自动补全代码
15 0
|
3天前
|
存储 编译器 C++
C ++初阶:类和对象(中)
C ++初阶:类和对象(中)
|
3天前
|
C++
C++(十六)类之间转化
在C++中,类之间的转换可以通过转换构造函数和操作符函数实现。转换构造函数是一种单参数构造函数,用于将其他类型转换为本类类型。为了防止不必要的隐式转换,可以使用`explicit`关键字来禁止这种自动转换。此外,还可以通过定义`operator`函数来进行类型转换,该函数无参数且无返回值。下面展示了如何使用这两种方式实现自定义类型的相互转换,并通过示例代码说明了`explicit`关键字的作用。