0.
c++的第一个要学习的特性,结构体中可以添加函数。这里operator是关键字表示操作符,这是对操作符的重载,即重新给这个操作符下定义(该结构体下)。参数表中的const表示不会对s1,s2指向的内容修改,而最后const对函数的修饰表示保证函数执行时不会对类或结构内部的变量进行更改。方便后期的维护。
辨析下面两句的区别:
char chs[] = "123";
const char* ch1 = chs;
char* const ch2 = chs;
ch1说的是 chs的内容不会被改变
ch2则是指 ch2指向的内容不会改变,即他就是指向chs
1.
这个要说的是命名空间,因为有可能一个程序有多个人来编写,这些人可能会写出名称一样的函数,为了避免冲突而又不进行大范围的更改,产生了命名空间的概念,不同的空间可以有同名的函数或类等等,只要在调用时声明是哪个命名空间里的就可以,使用using表示默认的命名空间,这样在调用时就可以省略对命名空间的声明了。
2.
这是模板类的用法。template<class type>表示一个模板,template修饰着紧接着的下一个类或结构或函数。因为有很多事情基础结构是一样的,只是由于对象的类型不同而造成了些微的差异,我们就可以把这件事抽象成一个模板类,在使用时根据实际需要表明他的类型,此时的特定类型如int就会替换模板中的type。
上图中是一个指针类的简单模板,首先private不可引用是缺省行为,指的是会产生一个T类型的指针。public的两个构造函数结合main中的调用来看,这里出现了=的一个语法糖,它不是赋值而是在传参数,把&num给了intptr,那么回到类中由于有参数会调用Myptr(T* p)。
再接下来重载了*运算符,首先注意这个函数的返回值是引用,引用表示“在原址上进行操作”,确保了返回值不会是一个备份变量,如果是T*,那么在调用时则会是*(*intptr) = 1。
声明MyPtr类可以有效的避免malloc/new之后忘记free/delete的问题,解决方案就是用构析函数,~Myptr表示一旦变量被销毁之后的操作。
这是一个更复杂一些的模板,接受三个类,产生的是一个函数指针。
一个大程序:
#include <iostream>
#include <map>
#define NULL 0
namespace lll
{
// 对指针的引用计数
class _MyPtr
{
private:
static std::map<int, int> refcount;
template<class T>
static void Dispose(T* ptr)
{
if (GetCount(ptr) < 1)
{
free(ptr);
}
else
{
// doing nothing or throw an exception
}
}
static int GetCount(int addr)
{
std::map<int, int>::iterator ite = refcount.find(addr);
if (ite == refcount.end())
return 0;
else
return (*ite).second;
}
template<class T>
static int GetCount(T* ptr)
{
return GetCount((int)ptr);
}
static void ModifyCount(int addr, int count)
{
std::map<int, int>::iterator ite = refcount.find(addr);
if (ite == refcount.end())
refcount.insert(std::make_pair(addr, count));
else
(*ite).second = count;
}
template<class T>
static void ModifyCount(T* ptr, int count)
{
return ModifyCount((int)ptr, int count);
}
static void AddCount(int addr)
{
std::map<int, int>::iterator ite = refcount.find(addr);
if (ite == refcount.end())
refcount.insert(std::make_pair(addr, 1));
else
(*ite).second = (*ite).second + 1;
}
template<class T>
static void AddCount(T* ptr)
{
AddCount((int)ptr);
}
template<class T>
static void SubCount(T* ptr)
{
std::map<int, int>::iterator ite = refcount.find((int)ptr);
if (ite == refcount.end())
{
throw std::exception("Invalid Operation");
}
else
{
(*ite).second = (*ite).second - 1;
if ((*ite).second < 1)
Dispose(ptr);
}
}
template<class T>
friend class MyPtr;
};
std::map<int, int> _MyPtr::refcount = std::map<int, int>();
template<class T>
class MyPtr
{
private:
T* ptr = NULL;
public:
static MyPtr<T> Alloc(int count)
{
int size = sizeof(T);
T* p = (T*)malloc(size * count);
for (int i = 0; i < count; i++)
{
new(p + i) T();
}
return MyPtr<T>(p);
}
#pragma region 构造/析构函数
public:
MyPtr()
{
std::cout << "def cont" << std::endl;
ptr = NULL;
}
MyPtr(T* p)
{
std::cout << "ptr cont" << std::endl;
ptr = p;
_MyPtr::AddCount(p);
}
MyPtr(MyPtr<T>& p)
{
std::cout << "ref cont" << std::endl;
ptr = p.ptr;
_MyPtr::AddCount(ptr);
}
~MyPtr()
{
std::cout << "descont" << std::endl;
_MyPtr::SubCount(ptr);
}
#pragma endregion
#pragma region 运算符
public:
MyPtr<T>& operator =(T* p)
{
if (p != ptr)
{
std::cout << "= ptr op" << std::endl;
if (ptr != NULL)
_MyPtr::SubCount(ptr);
ptr = p;
_MyPtr::AddCount(ptr);
}
return *this;
}
MyPtr<T>& operator =(MyPtr<T>& p)
{
if (p.ptr != ptr)
{
std::cout << "= mptr op" << std::endl;
if (ptr != NULL)
_MyPtr::SubCount(ptr);
ptr = p.ptr;
_MyPtr::AddCount(ptr);
}
return *this;
}
T& operator *()
{
if (ptr == NULL)
throw std::exception("Object reference not set to an instance of object");
else
return *ptr;
}
T* operator ->()
{
if (ptr == NULL)
throw std::exception("Object reference not set to an instance of object");
else
return ptr;
}
MyPtr<T> operator +(int offset)
{
return MyPtr(ptr + offset);
}
MyPtr<T> operator -(int offset)
{
if ((((int)ptr) - offset) < 0)
throw std::exception("out of index");
else
return MyPtr(ptr - offset);
}
int operator - (MyPtr<T>& p)
{
return ptr - p.ptr;
}
#pragma endregion
};
}
class CL
{
public:
CL()
{
std::cout << "cl cont" << std::endl;
}
~CL()
{
std::cout << "cl descont" << std::endl;
}
void Func()
{
std::cout << "123" << std::endl;
}
};
int main()
{
using namespace lll;
int mynum = 0;
MyPtr<int> numptr = &mynum;
*numptr = 1;
MyPtr<CL> clptr = MyPtr<CL>::Alloc(1);
(*clptr).Func();
clptr->Func();
return 0;
}