base1 和 base2
class base1
{
public:
virtual ~base1(){
cout << "~base1()" << "\n";
}
};
class base2 : public base1
{
public:
virtual ~base2() {
cout << "~base2()" << "\n";
}
};
_AnyHelper 与 _AnyHelperBase
class _AnyHelperBase
{
public:
virtual const std::type_info& Type()const = 0; // { return typeid(nullptr); }
virtual _AnyHelperBase* Clone() const = 0; //{ return nullptr; }
virtual bool Equal(const _any& r)const = 0; // { return false; }
virtual void* GetDataPointer()const = 0; // return null; }
virtual bool IsArray()const = 0;
};
template<typename T>
class _AnyHelper :public _AnyHelperBase
{
public:
/// <summary>
/// 用数组来保存T类型数据,如果是单个T类型数据,数据就是 _data[0],
/// 否则是 _data.GetDataPointer(),如字符串。
/// </summary>
lf::_Array<T> _data;
public: //-------------------------------构造
_AnyHelper(const T* pt, const size_t& nCount) {
_data.SetBuffer(nCount + 1);
_data.Add(pt, nCount);
_data.ZeroBufferAll();
}
/// <summary>
/// 拷贝构造
/// </summary>
/// <param name="r"></param>
_AnyHelper(const _AnyHelper& r) {
_data = r._data;
}
_AnyHelper() {}
public: //-----------------------------------重写
virtual const std::type_info& Type()const override
{
return typeid(T);
}
/// <summary>
/// 返回一个新的对象指针
/// </summary>
/// <returns></returns>
virtual _AnyHelper* Clone()const override
{
//见ClearMemory()
//return m.NewEmplace<_AnyHelper<T>>(*this);
return new _AnyHelper(*this);
}
/// <summary>
/// 原则:
/// 相同数据才判断是否相等
///
/// </summary>
/// <param name="r"></param>
/// <returns></returns>
/// 创建时间: 2024-11-23 最后一次修改时间:2024-11-23
virtual bool Equal(const _any& r)const override{
if (Type() == r._pData->Type()) {
return _data == ((_AnyHelper<T>*)r._pData)->_data;
}
return false;
}
virtual void* GetDataPointer()const override {
if (_data.size() == 0)
return nullptr;
else if (_data.size() == 1)
return &_data[0];
else
return _data.DataPointer();
}
virtual bool IsArray()const override {
return _data.size() > 1;
}
public: //-----------------------------------------运算符重载
};
可以运行
//下面代码可以运行
auto p2 = new _any::_AnyHelper<int>[1];
auto p1 = p2;
delete[] p1;
可以执行
//下面代码可以运行
auto p2 = new base2[1];
auto p1 = p2;
delete[] p1;
可以执行:
//下面代码可以运行
auto p2 = new base2[1];
base1* p1 = p2;
delete[] p1;
不能执行
//下面代码不可以运行
auto p2 = new _any::_AnyHelper<int>[1];
_any::_AnyHelperBase* p1 = p2;
delete[] p1;
base1 是 base2的基类,_AnyHelperBase也是_AnyHelper<int> 的基类,为什么结果却不同?

解决了,是因为_AnyHelperBase和_AnyHelper没有加上析构函数:
在_AnyHelperBase中
//一定要加上析构函数
virtual ~_AnyHelperBase(){}
在_AnyHelper中
//一定要加上析构函数
virtual ~_AnyHelper() { }
现在可以了:

为什么要有delete[],因为我要用上自己的内存管理函数:
/// <summary>
/// 直接构建一个新的MyClass,并返回它的一个指针。(好处免去初始化)
/// 用法例子:
///
/// list<int>* pl = NewEmplace<list<int>>(5,10); //申请一个列表内存指针(5个元素都是10的列表)
/// delete[] pl; //删除内存对象,分配时用new[]分配的
/// </summary>
/// <typeparam name="MyClass"></typeparam>
/// <typeparam name="...MyClassConstructorParameterTypes"></typeparam>
/// <param name="...MyClassConstructorParameters"></param>
/// <returns></returns>
/// 创建时间: 2024-10-01 最后一次修改时间:2024-10-01
template<typename MyClass, typename... MyClassConstructorParameterTypes>
static MyClass* NewEmplace(MyClassConstructorParameterTypes&&... MyClassConstructorParameters)
{
_obj_used += 1;
_mem_used = _mem_used + sizeof(MyClass);
/*
//不能用 delete[] 删除
return new MyClass(
std::forward<MyClassConstructorParameterTypes>(MyClassConstructorParameters)...);
*/
/*
list<int> il = { 1,2,3 };
std::list<int>* p2 = new std::list<int>[1] {il};
*/
//delete[] pl; //删除内存对象,分配时用new[]分配的
return new MyClass[1]
{
MyClass(
std::forward<MyClassConstructorParameterTypes>(MyClassConstructorParameters)...)
};
}
/// <summary>
/// 功能:释放内存,并把内存指针重置为0
///
/// 条款3:尽量以 new 和 delete 取代malloc 和 free
/// 分配内存,给对象分配内存不能用C语言的malloc函数, 因为 malloc函数不会调用用对象的
/// 构造函数,free函数不会调用对象的析构函数。
/// 条款5:使用相同形式的 new 和 delete
/// 游戏规则:如果你在调用 new 时使用了 [ ] ,则你必须在调用 delete 时也使用[] 。
/// 如果你在调用 new 的时候没有使用[],那么你也不应该在调用 delete 时使用[] 。
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="pMemory"></param>
/// <param name="nCount"></param>
/// 创建时间:????-??-?? 最后一次修改时间:2024-11-29
template<typename T> static void Delete(T* &pMemory, int nCount)
{
_obj_used -= nCount;
_mem_used -= sizeof(T) * nCount;
delete[] pMemory;
pMemory = null;
}
/// <summary>
/// 功能:分配内存。
///
/// 条款3:尽量以 new 和 delete 取代malloc 和 free
/// 分配内存,给对象分配内存不能用C语言的malloc函数, 因为 malloc函数不会调用用对象的
/// 构造函数,free函数不会调用对象的析构函数。
/// 条款5:使用相同形式的 new 和 delete
/// 游戏规则:如果你在调用 new 时使用了 [ ] ,则你必须在调用 delete 时也使用[] 。
/// 如果你在调用 new 的时候没有使用[],那么你也不应该在调用 delete 时使用[] 。
/// </summary>
/// <typeparam name="T">数据类型</typeparam>
/// <param name="nCount">分配个数</param>
/// <returns></returns>
/// 创建时间: ????-??-?? 最后一次修改时间:2024-12-08
template<typename T> static T * New(const int& nCount, const bool& bZero = false)
{
//std::cout << "分配对象为:" << "T" << typeid(T).name() << "\t 个数nCount="<< nCount << "\n";
if (nCount <= 0) return null;
if (nCount > _memory_allow_max)
{
throw "超出最大充许申请的对象数";
}
_obj_used += nCount;
_mem_used = _mem_used + sizeof(T) * nCount;
/*
if (bZero) //初始化内存为0
{
T* pt = new T[nCount];
for (int i = 0; i < nCount; ++i)
{
pt[i] = T();
}
return pt;
}
else
{
return new T[nCount];
}
*/
/*
int (*pia = new int[10]; //10个未初始化的int
int *pia2 = new int [10](); //10个值初始化为0的int
string *psa = new string[10]; //10个空string
string *ps2 = new string[10](); //10个空string
*/
if (bZero) {
return new T[nCount]();
}else {
return new T[nCount];
}
}