关于new表达式
- new表达式可分解为两个操作:
①向程序的空闲空间请求内存,若分配到足够空间,则返回指针,指向新对象;若未分配到足够空间,则抛出异常bad_alloc(异常处理)
②如果new 类型名(初值),则该新对象被初始化。
举个class类型的例子:
_root = new BTnode<elemType>(elem);
其中elem被传入BTnode模板类的类构造函数。分配内存失败,初始化操作(类构造函数操作)不会发生。
模板类成员函数的定义/声明实战:
举几个例子吧,主要为了熟悉语法!
一般模板类成员函数(看看格式就好,不必计较太多)定义:
template<typename valType>
void BTnode<valType>::
insert_value(const valType &val)//注意这里的格式
{
if(val==_val)
{
_cnt++;
return;
}//二叉树有这个结点了,就把结点插入次数记录下来即可
if(val<_val)
//插入的结点比当前结点小,就插到当前结点的左孩子(如果当前结点的左孩子没有)
{
if(!_lchild)
{
_lchild=new BTnode(val);
}
else//当前结点的左孩子有了,插入到当前结点的左孩子的左孩子或右孩子结点
{
_lchild->insert_value(val);//递归调用去插入到当前结点的左孩子的左孩子或右孩子结点
}
}
else
//插入的结点比当前结点大,就插到当前结点的右孩子(如果当前结点的右孩子没有)
{
if(!_rchild)
{
_rchild=new BTnode(val);
}
else
{
_rchild->insert_value(val);
}
}
}
内联模板类成员函数(看看格式就好,不必计较太多)定义:
template<typename elemType>
inline void BinaryTree<elemType>::
remove(const elemType &elem)//注意这里的格式!
{
if(_root)
{
if(_root->_val==elem)
{
remove_root();
}
else
{
_root->remove_value(elem,_root);
}
}
}
一般模板类成员函数的声明:
template<typename valType>
void BTnode<valType>::
remove_value(const valType &val,BTnode *&prev);
//关于*&的解释下面有说
模板类成员函数的定义/声明格式
OK,摸清楚大概格式了。即
注意分三行写这种让代码清晰简洁的写法👇
template<typename 自定义类型名(占位符)>
(自己决定这里加不加inline) 返回类型 模板类类名<自定义类型名>::
模板类成员函数名(参数表(比如const 自定义类型名 &参数名等));或者{//。。。}
函数参表出现了*&的说明
- 复习一下,参表的参数以&方式传递,为了避免当模板自定义类型名(<typename 巴拉巴拉>中的巴拉巴拉)被指定为class类型时,因传值(不带&)而产生的昂贵复制开销。
- 不改变参数值,就再该参数名的声明最前加个const,即const 类型名 参数名…
*&
即为指针的引用*&
出现在函数参表中的意思就是我**既想改变传入形参的实参指针(或说形参指针)所指的对象,又想改变实参(或说形参)指针本身**- 实例:
template<typename valType>
void BTnode<valType>::
remove_value(const valType &val,BTnode *& prev)//删除二叉树的一个结点(非根结点)
//根结点删除另有其他BTnode类成员函数去管,这里不用多虑
{
//在二叉树中自顶向下搜索要删除的结点
if(val<_Val)
{
if(!_lchild)
{
return;
}
else
{
_lchild->remove_value(val,_lchild);
}
}
else if(val>_val)
{
if(!_rchild)
{
return ;
}
else
{
_rchild->remove_value(val,_rchild);
}
}
else//找到要删除的二叉树的结点了
{
if(_rchild)
{
prev=_rchild;//这里改变了形参(实参)指针的指向,即“又想改变实参(或说形参)指针本身”
//*prev=....可以理解为想改变传入形参的实参指针(或说形参指针)所指的对象
//(需要有重载运算符=,而且是模板函数形式的重载运算符函数,下节会说)
if(_lchild)
{
if(!prev->_lchild)
{
prev->_lchild=_lchild;
}
else
{
BTnode<ValType>::lchild_leaf(_lchild,prev->_lchild);
}
}
}
else
{
prev=_lchild;
}
}
delete this;//删除二叉树中我想删除的结点(即一个BTnode类类对象)
}