抽象基类运用与抽象基类指针作为模板容器元素
2016-04-25 23:35
344 查看
// 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;// 取头结点指针赋值为空
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C与C++之间相互调用实例方法讲解
- 解析C++中派生的概念以及派生类成员的访问属性