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


目录
相关文章
|
18天前
|
存储 安全 C语言
C++ String揭秘:写高效代码的关键
在C++编程中,字符串操作是不可避免的一部分。从简单的字符串拼接到复杂的文本处理,C++的string类为开发者提供了一种更高效、灵活且安全的方式来管理和操作字符串。本文将从基础操作入手,逐步揭开C++ string类的奥秘,帮助你深入理解其内部机制,并学会如何在实际开发中充分发挥其性能和优势。
|
21天前
|
编译器 C++
㉿㉿㉿c++模板的初阶(通俗易懂简化版)㉿㉿㉿
㉿㉿㉿c++模板的初阶(通俗易懂简化版)㉿㉿㉿
|
7天前
|
安全 C++
【c++】模板详解(2)
本文深入探讨了C++模板的高级特性,包括非类型模板参数、模板特化和模板分离编译。通过具体代码示例,详细讲解了非类型参数的应用场景及其限制,函数模板和类模板的特化方式,以及分离编译时可能出现的链接错误及解决方案。最后总结了模板的优点如提高代码复用性和类型安全,以及缺点如增加编译时间和代码复杂度。通过本文的学习,读者可以进一步加深对C++模板的理解并灵活应用于实际编程中。
24 0
|
18天前
|
存储 安全 算法
深入理解C++模板编程:从基础到进阶
在C++编程中,模板是实现泛型编程的关键工具。模板使得代码能够适用于不同的数据类型,极大地提升了代码复用性、灵活性和可维护性。本文将深入探讨模板编程的基础知识,包括函数模板和类模板的定义、使用、以及它们的实例化和匹配规则。
|
2月前
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
48 5
|
4月前
|
安全 编译器 C++
【C++11】可变模板参数详解
本文详细介绍了C++11引入的可变模板参数,这是一种允许模板接受任意数量和类型参数的强大工具。文章从基本概念入手,讲解了可变模板参数的语法、参数包的展开方法,以及如何结合递归调用、折叠表达式等技术实现高效编程。通过具体示例,如打印任意数量参数、类型安全的`printf`替代方案等,展示了其在实际开发中的应用。最后,文章讨论了性能优化策略和常见问题,帮助读者更好地理解和使用这一高级C++特性。
142 4
|
4月前
|
算法 编译器 C++
【C++】模板详细讲解(含反向迭代器)
C++模板是泛型编程的核心,允许编写与类型无关的代码,提高代码复用性和灵活性。模板分为函数模板和类模板,支持隐式和显式实例化,以及特化(全特化和偏特化)。C++标准库广泛使用模板,如容器、迭代器、算法和函数对象等,以支持高效、灵活的编程。反向迭代器通过对正向迭代器的封装,实现了逆序遍历的功能。
55 3
|
4月前
|
编译器 C++
【c++】模板详解(1)
本文介绍了C++中的模板概念,包括函数模板和类模板,强调了模板作为泛型编程基础的重要性。函数模板允许创建类型无关的函数,类模板则能根据不同的类型生成不同的类。文章通过具体示例详细解释了模板的定义、实例化及匹配原则,帮助读者理解模板机制,为学习STL打下基础。
53 0
|
18天前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
21天前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)