抽象基类运用与抽象基类指针作为模板容器元素

// abstractclass.cpp : Defines the entry point for the console application.
//


#include "stdafx.h"
#include <vector>
using namespace std;


class A
{
public:
<span style="white-space:pre">	</span>virtual void f() = 0;
};


class B : public A
{
public:
<span style="white-space:pre">	</span>void f()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">	</span>}
};


int _tmain(int argc, _TCHAR* argv[])
{
<span style="white-space:pre">	</span>vector<A *> vec(10);// 我们不可以声明抽象基类对象,但是可以声明抽象基类对象的指针
<span style="white-space:pre">	</span>vec[0] = new B;
<span style="white-space:pre">	</span>vec[0]->f();// 对抽象基类纯虚函数的调用,执行的是派生类的同名成员函数
<span style="white-space:pre">	</span>delete vec[0];
<span style="white-space:pre">	</span>return 0;
}


// abstractbasepointerastemplatecontainerelement.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

// 模板容器
template <class T>
class vector
{
public:
	T m[10];
};

// 抽象基类
class A
{
public:
	virtual void f() = 0;
};

// 派生类
class B : public A
{
public:
	void f()
	{
	}
};

int _tmain(int argc, _TCHAR* argv[])
{
	// 将抽象基类的指针作为模板容器的元素
	vector<A *> vec;
	// 动态创建派生类的对象,以抽象基类的指针指向
	A *p = (A *)new B;
	// 将指向派生类对象的抽象基类的指针入队
	vec.m[0] = p;
	// ...
	// 将指向派生类对象的抽象基类的指针出队
	A *q = vec.m[0];
	// 此时,对抽象基类纯虚函数的调用,转为对派生类成员函数的调用
	q->f();
	// 动态释放派生类的对象
	delete q;
	return 0;
}

// remark i:变量都要初始化,指针尤其需要初始化,模板容器中的抽象基类指针也不例外:
	vector<A *> vec(1);
	vec[0] = NULL;

// remark ii:因此,比如,对于一个带头结点的指针链表,要记得对其头结点进行初始化置为空。
	LinkList()// 构造函数
	{
		m_head = new char *;
		m_head->data = NULL;// 头结点
		...
	}

// remark iii:但是,如果这个指针链表是一个以指针为元素的模板链表,那么初始化置空头结点的操作就不应该在模板链表的构造函数中进行,
	LinkList()// 构造函数
	{
		m_head = new Node<T>;
		memset(m_head->data, NULL, sizeof(T));// !不要在模板基类的构造函数中直接赋值元素!
	}
因为这样会一起置空其他的以具有自己构造函数的类为元素的类链表的头结点。例如一个初始时具有1个元素('\0')的字符串类:
	String()// 构造函数
	{
		m_p = new char[1];
		m_len = 1;
		m_p[0] = '\0';//初始时具有1个元素('\0')
	}
以这种模板链表为模板,定义以字符串类为元素的字符串链表,那么链表头结点其成员m_len,m_p都将被值为0。

// remark iv:正确的写法是,模板链表初始化时,对头结点多态地赋值一个模板类型的数据:
	LinkList()// 构造函数
	{
		m_head = new Node<T>;
		m_head->data = T();// 模板类型
	}
其中,模板类型的赋值操作其实在Node类的合成拷贝构造函数中已经隐含了。所以有一种更简洁的方法,就是省去模板类型显式赋值,使用new操作符,隐式地而且多态地调用模板类型的构造函数,对头结点进行初始化:
	LinkList()// (推荐)构造函数
	{
		m_head = new Node<T>;
	}
此时如果定义一个字符串链表,头结点也能够具有1个元素('\0')。

// remark v:但是,仍然需要注意,如果模板链表的模板类型是指针,因为指针本身是不会自动初始化的,所以需要记得在定义以指针为元素的模板链表时,对其头结点手动初始化,或者对模板链表继承后定义继承类构造函数对指针初始化。
	LinkList<char *> linklist;
	linklist.m_head->data = NULL;// 取头结点指针赋值为空

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值