本专栏文章列表
一、何为面向对象
二、C语言也能实现面向对象
三、C++中的不优雅特性
四、解决封装,避免接口
五、合理使用模板,避免代码冗余
六、C++也能反射
七、单例模式解决静态成员对象和全局对象的构造顺序难题
八、更为高级的预处理器PHP
九、Gtkmm的最佳实践
本系列文章由 西风逍遥游 原创,转载请注明出处:西风广场 http://sunxfancy.github.io/
五、合理使用模板,避免代码冗余
下面我们来讨论一下,如何解决模板的不易封装的问题。
我们提供这样一种思路,对于链表一类的通用类型,我们尽量采取强制类型转换的方式,尽量避免模板的滥用。
同样,我们应该避免对结构体的直接存储,尽量使用类似java的指针传递方式来传递对象。
我们首先来写一个单类型的list
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| #ifndef LIST_C_H #define LIST_C_H
class list_c_private; struct list_c_node;
class list_c { public: list_c(); ~list_c();
void insert(void*); int size(); void* get(int);
protected: list_c_private* priv; };
#endif // LIST_C_H
|
这里我们使用了上面讲到的封装方式,降低了类间的耦合度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| #include "list_c.h"
class list_c_private { public: int size; list_c_node* head; };
struct list_c_node { void* data; list_c_node* next;
list_c_node() { data = next = nullptr; } };
list_c::list_c() { priv = new list_c_private(); priv->head = new list_c_node(); }
list_c::~list_c() { delete priv; }
void list_c::insert(void* data) { list_c_node* p; for (p = priv->head; p->next != nullptr; p = p->next) {} p->next = new list_c_node(); p->next->data = data; }
int list_c::size() { return priv->size; }
void* list_c::get(int k) { int t; list_c_node* p; for (p = priv->head->next, t = 0; p != nullptr && t != k ; p = p->next, ++t) {} return p->data; }
|
这是一个简单的链表,只是作为示例使用,写了插入和获取的两个方法。
而为了通用性支持,我们写一个模板,进行类型的强制转换:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #ifndef LIST #define LIST
#include "list_c.h"
template<typename T> class list { public: list() { clist = new list_c(); } ~list() { delete clist; }
void insert(T data) { clist->insert((void*)data); }
int size() { return clist->size(); }
T get(int k) { return (T)clist->get(k); }
protected: list_c* clist; };
#endif // LIST
|
这样,带来的好处有,首先能够将模板封装操作,其次,能够在封装类中,动态的调整内部实例。
对于一个传入的类型,你可以判断一下,是否适合当前的模板,如果不适合,可以在其中动态的报错。
最后是模板的使用:
1 2 3 4 5 6 7 8 9 10 11 12 13
| #include <iostream> #include "list" using namespace std;
int main(){ list<long> testlist; testlist.insert(10); testlist.insert(20);
long k = testlist.get(1); printf("%d\n", k); return 0; }
|