1. 如何防止头疼的C++文件交叉包含。
文件夹名(或库名):
1. 每个库中有以branch_开头命名的文件和以global_开头命名的文件,且都是静态类。
2. 如果要用到所有库的功能,只需包含一个文件 global_ + 库名.h
3. 所有放入库的文件都不能包含 global_ + 库名.h。
4. global_ + 库名.h 有一个类,它是继承自所有以 branch_开头的文件中的类,这些类都是以静态成员函数构成的类。
5. global_ + 库名.h 中的命名规则为 global_库名 , branch_ + 库名.h 命名规则为: branch_库名 + name
6. 库中任何文件可以包含 branch_开头的文件,但不能包含同文件夹中以 global_开头的文件
7. 当库为层次包含关系时,列如:
std => Linux, Windows
Linux中不能包含任何 Windows 库中的文件,同时 Windows 也不能包含任何 Linux文件,但都可以包含 std 中的文件。
std 不能包含任何 Linux,Windows 中的.h文件
例如,有三个文件夹,std,Linux,Windows
branch_std_name1.h 中 不包含任何 A 中任何 .h文件
static class branch_std_name1
{
public:
static void do_something1;
};
branch_std_name2.h 中 不包含任何 A 中任何 .h文件
static class branch_std_name2
{
public:
static void do_something2;
};
global_std.h 中 可以包含任何 A 中的 .h文件
#include "branch_a_name1.h"
#include "branch_a_name2.h"
#include "mylist.h"
#include "mystring.h"
static class global_a : public branch_a_name1, branch_a_name2
{
};
static class global_b : public global_a
{
};
最后一个,为了便于书写,可以定义一个简单易记的静态类:
例:
static class ga : public global_a {}
static class gb : public global_b {}
或定义别名: typedef global_c gc;
typedef global_b gb;
最后:
最好 ga 就是全局类,是最终的命名,在任何地方都是名子 ga:: //gloabl all
基中 ga 就是包含所有的全局静态函数。
这样设计就是防止C++头疼的文件交叉包含。
2. 自定义类要尽量定义比较大小的运算符。否则使用有排序功能
的泛型类会编译出错,有时候很难排查!
例:
3. 定义一个全局内存管理类,所有 new 和 delete 都使用这个类。
例如:
memory_.h
/*******************************************************************************************
文件名 : memory_.h
作者 : 李锋
功能 : 内存操作
创建时间 : 2016年7月6日
最后一次修改时间 : 2022年09月23日
********************************************************************************************/
#ifndef _MEMORY__H_
#define _MEMORY__H_
#include"macro_.h"
#include <assert.h>
_LF_BEGIN_
//内存操作类
class memory_ {
public:
//全局内存对象计数器
static __int64 _obj_used;
static __int64 _mem_used;
//充许最大内存数量
static int _memory_allow_max;
public:
memory_();
~ memory_();
static inline int allow_max() { return _memory_allow_max; }
//内存使用量,字节
static inline __int64 mem_used() { return _mem_used;}
//对象使用量
static inline __int64 obj_used() { return _obj_used; }
public:
//分配内存,给对象分配内存不能用C语言的malloc函数
template<typename T> static T * memNew(int nCount, bool bDefaultValue = false){
//std::cout << "分配对象为:" << "T" << typeid(T).name() << "\t 个数nCount="<< nCount << "\n";
if (nCount == 0) return null;
if (nCount > _memory_allow_max){ throw "超出最大充许申请的对象数"; return 0; }
_obj_used += nCount;
_mem_used = _mem_used + sizeof(T) * nCount;
if (bDefaultValue){
return memory_::memset_<T>(new T[nCount], nCount, T());
}
else{
return new T[nCount];
}
}
//释放内存
template<typename T> static void memDelete(T *pMemory, int nCount){
_obj_used -= nCount;
_mem_used -= sizeof(T) * nCount;
delete[] pMemory;
pMemory = null;
}
//设置值
template<typename T> static T *memset_(T *pMem,const int nCount, const T &rDefaultValue){
assert(pMem != null);
for (int n = 0; n < nCount; ++n)
*(pMem + n) = rDefaultValue;
return pMem;
}
//每一个类必须写 T& T::operator=(const T &rhs)
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="pDestination"></param>
/// <param name="pSource"></param>
/// <param name="nCount"></param>
/// <returns></returns>
/// 创建时间: ????-??-?? 最后一次修改时间:2021-10-26
template<typename T> static T *memcpy_(T *pDestination, const T *pSource, const int nCount){
assert(nCount != 0 && pDestination != null && pSource != null);
for (int n = 0; n < nCount; ++n)
{
pDestination[n] = pSource[n];
}
return pDestination;
}
};
/// <summary>
/// 内存管理,内存自动释放
/// </summary>
/// <typeparam name="T"></typeparam>
template<typename T>
class mem {
private:
int _nCount;
public:
T* data;
int effectiveCount = 0; //有效数据个数
const int& count() const { return _nCount; }
mem(const int& nCount) {
_nCount = nCount;
data = memory_::memNew<T>(nCount, false);
}
~mem() {
memory_::memDelete<T>(data, _nCount);
}
};
_LF_END_
#endif //--------------------------------------------------------------------------- !_memory__H_
memory_.cpp
#include"memory_.h"
_LF_BEGIN_
__int64 memory_::_obj_used = 0;
__int64 memory_::_mem_used = 0;
int memory_::_memory_allow_max = 1073741824; //1024 * 1024 * 1024; 1MB
memory_::memory_()
{
}
memory_::~memory_()
{
}
_LF_END_
4. 所有自定义类没有指针类数据成员,都不用定义拷贝构造函数,因为编译器会自动为你实施了最好的行为,其实根本的原因就是 memcpy 比你写的的拷贝构造函数更有效率。
例子:
对于自己定义拷贝构造
Point3d(const Point3d& p3d) {
_x = p3d._x;
_y = p3d._y;
_z = p3d._z;
}
编译提供的是 bitwise copy => memcpy(b,&a,sizeof(a));
实际上就是:
5 .
6 .
...............就这样吧,有时间再继继,下次再更新。