随笔分类 -  C++编程

摘要:对于C++模板,其强大和高深早已为业界所共识。相比于其他语言,C++是在设计之初便已经提供了对泛型和模板的支持。然而随着语言的发展,与其相关的库也是层次不穷,其中的佼佼者主要为STL(已为C++标准库)、Boost和Loki等。很多酷爱C++的开发者投入了大量的时间和精力去深入的研习它们,当然回报也是相当丰厚的,因为他们的能力以及设计理念较之以前相比也确实得到了较大的提高。这个C++模板系列博客,主要还是以C++模板基础为主,同时也提供了一些常用的技巧,而更多的技巧还是需要开发者自己通过阅读大量的C++模板库代码去获悉和提高。 Step By Step(C++模板函数)http://www.. 阅读全文
posted @ 2012-09-12 08:56 OrangeAdmin 阅读(7872) 评论(4) 推荐(6) 编辑
摘要:一、命名模板参数: 有些高级脚本语言,如Perl、PL/SQL等,他们的函数参数在调用时都支持命名参数,既在调用时可以不按照顺序传递参数,而是p可以按照参数的名字传递。先看下面的代码示例: template<typename Policy1 = DefaultPolicy1, typename Policy2 = DefaultPolicy2, typename Policy3 = DefaultPolicy3, typename Policy4 = DefaultPolicy4> class BreadSlicer { ... ... } 上面的模板类含有4个模板参数,如果要想指 阅读全文
posted @ 2012-09-10 09:27 OrangeAdmin 阅读(7416) 评论(0) 推荐(2) 编辑
摘要:一、Policy类: 该篇博客中的代码示例将承接上一篇博客(C++模板Trait)中给出的累加器的例子。在之前的代码中,我们都是让累加器完成固定的累加行为,即累加求和。然而事实上,我们仍然可以修改该函数的累加算法,比如将求和算法改为求积算法。或者说,如果参数类型是字符的话,我们也可以通过该函数进行指定形式的字符连接。在实际的代码修改中,我们只需将total += *begin代码行替换为我们为该函数指定的Policy模板参数,这样我们就将该模板参数称为该函数累加过程的一个Policy。见如下代码示例和关键性注释: 1 #include <stdio.h> 2 3 te... 阅读全文
posted @ 2012-09-07 07:12 OrangeAdmin 阅读(4973) 评论(1) 推荐(2) 编辑
摘要:Trait是C++模板设计的一个基本应用技巧,通过应用Trait模板参数,可以在工业强度的程度设计中既保证了程序的灵活性,同时也有效的减少了类型参数的数量。对于普通函数而言,如果想要对该函数的功能进行更为细粒化的控制,一个主要的方法便是为该函数增加更多的参数,而函数体内的逻辑代码则会根据参数值的不同而选择不同的逻辑分支,最终返回不同的结果。一个极端的现象是函数的参数过多,而且并不是每个参数都会为每个调用者所用,如果简单的使用缺省值,那么这些缺省参数则必须位于函数参数的末尾。如果有朝一日需要新增函数参数,而该参数恰恰又没有缺省值,此时我们只能将该新增的参数放到所有缺省参数的前面,一旦如此,已有. 阅读全文
posted @ 2012-09-05 09:13 OrangeAdmin 阅读(8480) 评论(4) 推荐(3) 编辑
摘要:一、模板函数重载: 函数重载是一个非常通用亦非常容易理解的编程基础概念,既函数名相同而函数签名不同的一组函数,在实际的调用中,编译器会根据函数参数的不同自动选择最为合适且最为特化的函数。在推演的过程中,如果出现多个函数均符合该调用规则,编译器将根据其内置的特化规则,选择最为特殊的函数作为候选函数。然而如果仍有多个候选函数的话,编译器将报出二义性错误。和普通函数一样,在C++中模板函数也同样支持函数重载的功能,甚至可以将模板函数与普通函数混合在一起,以达到更为灵活的函数重载的效果。 在这里,我们对于函数重载的概念本身将不再做过多的赘述了,而是将重点放在模板函数重载的应用场景和应用技巧上。下面我将 阅读全文
posted @ 2012-09-03 07:07 OrangeAdmin 阅读(4995) 评论(3) 推荐(3) 编辑
摘要:普通重载函数可以通过函数参数进行推演,并由编译器选定最适合的重载函数作为候选函数。与此类似,模板函数可以通过函数参数的类型推演出该函数模参的实际类型。C++的编译器在完成类型推演的过程中有以下一些技巧和注意事项,这里我们将尽可能的列出最为常用的规则,并给出相应的示例以便于理解。 1. 最基本的模板函数类型推演。见以下代码示例、关键性注释和输出结果。 1 #include <stdio.h> 2 #include <typeinfo.h> 3 4 template<typename T> 5 void func1(T* t) { 6 p... 阅读全文
posted @ 2012-08-31 07:43 OrangeAdmin 阅读(3342) 评论(0) 推荐(3) 编辑
摘要:一、符号查找: 这里先给出两个基本的术语,它们将在后面的篇节中被广泛的引用。 1. 限定作用域符号: 如果一个名称(函数名、类名或变量名)的前面包含域解析运算符(::),或成员访问运算符(. or ->),这表明该名称将属于某一作用域,那么我们就将该类名称成为限定作用域符号。如:::GetTickCount()、myClass->GetCount()等。与其相反的我们则成为非限定作用域符号,如:GetCount(),GetTickCount()等。 2. 依赖型符号: 如果一个名称依赖于某个模板参数,如:vector<T>::iterator,这里由于T是一个模板参数, 阅读全文
posted @ 2012-08-29 09:39 OrangeAdmin 阅读(3406) 评论(0) 推荐(2) 编辑
摘要:一、模板类静态数据成员的定义: 在下面的代码中,我们给我一个基于模板的单实例类SingletonClass,同时在该类中给出获取单实例和释放单实例的两个静态方法。这样,对于其他需要具有单实例功能的其他类直接继承该类便可同样具有了单实例的功能,该技巧可同样应用于引用计数功能。在下面的例子中,我们在模板类中声明了一个静态成员来表示单实例对象,和普通类的静态成员一样,该静态成员同样需要在外部被定义,但是其定义的规则在语法上普通类稍有不同,这一点可以在下面的示例中体现出来。 1 #include <stdio.h> 2 3 template<typename T> 4 ... 阅读全文
posted @ 2012-08-27 09:18 OrangeAdmin 阅读(8415) 评论(3) 推荐(1) 编辑
摘要:一、typename的另一种使用方式: 在此之前,我们了解到的有关该关键字的用途更多是针对模板参数的定义。而这里介绍的使用方式则有些不同,主要区别是typename的这种使用方式用于定义或提示编译器,其后修饰的标识符为模板参数中的类型标识符,而不是普通的静态类成员。见以下代码示例和关键性注释。 1 #include <stdio.h> 2 3 template<typename T> 4 class MyTestClass { 5 public: 6 //这里的typename是用于通知编译器,其后的MyType是模板T定义的内部类型,从这个代... 阅读全文
posted @ 2012-08-24 09:16 OrangeAdmin 阅读(5480) 评论(1) 推荐(3) 编辑
摘要:和函数一样,C++中的class也可以类型参数化,其中容器类是极具这一特征的。对于模板类的基本定义和使用,可以参考STL,这里就不做过多的赘述了。下面将主要介绍一下与其相关的高级实用特征。一、模板的特化: 这里可以先将类模板特化与面向对象中的多态进行一个简单的比较,这样可以便于我们对它的理解,也同样有助于指导我们在实际的开发中应用这一C++技巧。众所周知,对于多态而言,提供的是统一的接口和不同的实现类实例,其最终的行为将取决于实现类中的实现,相信每一个有面向对象基础的开发者对于这一概念并不陌生。而模板特化则要求必须提供一个标准的模板类(等同于多态中的接口),与此同时再为不同的类型提供不同的特. 阅读全文
posted @ 2012-08-22 07:13 OrangeAdmin 阅读(8877) 评论(13) 推荐(2) 编辑
摘要:一、模板函数实例化: 存在这样一种函数,它们在行为上是完全一致的,而不同只是函数的参数类型。对于这种类型的函数,我们可以应用C++模板和泛型来帮助我们更优雅和更具技巧性的的解决一些程序设计上的实际问题。如:1 template <typename T> 2 inline T const& max(T const& a, T const& b) {3 return a < b ? b : a;4 } 对于上面的模板函数,我们在实际的应用中可以用任意类型来实例化该模板函数,如:1 int main() {2 printf("The m... 阅读全文
posted @ 2012-08-20 07:52 OrangeAdmin 阅读(10553) 评论(5) 推荐(8) 编辑
摘要:二、字符串对象(string vs String): 在Java的代码中,我们经常会看到这样一种写法,相信几乎每一个Java程序员都有过这样的代码,因此他看上去非常熟悉,甚至还带有一点儿亲切感。1 public String getName() {2 return name;3 } 这样的代码在Java中确实司空见惯,也无可厚非,因此对于我们来说没有太多可以讨论的空间,除非你非常希望了解JVM中对象常量池的概念,然而它并不是我们这个条目中将要讨论的主题。 那么现在让我们来看一下在C++中又是如何处理此类问题的,下面将列举出三种最常用的实现方式。 方法一: ... 阅读全文
posted @ 2012-08-15 09:08 OrangeAdmin 阅读(3533) 评论(12) 推荐(5) 编辑
摘要:一、关联性容器(map vs TreeMap): 我们在用Java进行编程时经常会用到Map这样的容器接口,而它的具体实现类一般来自于TreeMap和HashMap,前者提供了有序性,而后者则在存取效率方面有着一定的优势。相比于Java,C++的STL也提供了map容器,其功能等同于Java中的TreeMap,至于HashMap,它并没有进入C++标准模板库。而幸运的是,现有的主流C++编译器供应商均提供了标准模板库的扩展包,并在该扩展包中实现了hash_map容器类,其接口标准和STL中的容器基本一致。 在本条目中我们将主要列举TreeMap(Java)和map(C++)在设计上的主要差.. 阅读全文
posted @ 2012-08-13 09:28 OrangeAdmin 阅读(5121) 评论(1) 推荐(4) 编辑
摘要:在实际的开发过程中,我们的项目或产品通常都会用到一些第三方开源组件或商业组件,以帮助开发人员实现一些特定的通用功能,如xml解析,正则表达式解析和数据压缩等。一般而言,只有在这两者均无法满足现有需求的情况下,我们才会考虑自行研发。因为适当的应用第三方组件可以保证开发人员能够将更多的精力投入到产品的核心算法和核心业务逻辑上,从而确保产品的开发周期和产品质量均能达到客户与公司满意的程度。 相比于开源组件,很多商业组件都提供了更易于操作的用户界面,丰富的文档和示例代码,以及更灵活的接口和更多的功能。通常而言,一旦我们选定了某一商业组件,它所提供的功能就已经可以满足我们的需求了。然而对于开源组件却.. 阅读全文
posted @ 2012-08-10 09:27 OrangeAdmin 阅读(3185) 评论(2) 推荐(2) 编辑
摘要:结果如何呢?我的VC++测试用例还是不能调用该接口的接口方法,只是这次的报错方式有所改变,提示是每个C/C++程序员最不愿意看到的“内存地址访问违规”,这一次我确实被郁闷了,这是为什么呢?五、gcc和VC++对象模型的差异分析: 在VC++中,C++对象(含有虚函数)在编译后将生成属于自己的对象模型,虚拟表vtable和虚拟指针vptr均被包含在该模型中(关于该问题,可以参考Stanley Lippman的《深度探索C++对象模型》)。而我们目前的设计方式恰恰是充分利用了vptr和vtable来定位每个接口函数,不幸的是,VC++生成的C++对象的vptr在该对象模型的最开始处,即该对象... 阅读全文
posted @ 2011-10-27 07:22 OrangeAdmin 阅读(2164) 评论(0) 推荐(2) 编辑
摘要:零、前言: 该篇博客的Title原计划是“在VC++中调用libmemcached的设计技巧”,可结果却事与原违,原因很简单,移植失败了。尽管结果如此,然而这3天的付出却是非常值得的,原因也很简单,收获非常大。事实上,我曾经在6月份的时候成功移植了当时的最新版本0.49,并写出了下面的博客: http://www.cnblogs.com/stephen-liu74/archive/2011/06/20/2084882.html 这次移植的目标非常明确,就是基于上次的经验,对libmemcached进行基于C++的封装,以便其可以更好的集成到我的底层服务框架中,使我的程序在Windows平... 阅读全文
posted @ 2011-10-24 07:31 OrangeAdmin 阅读(3284) 评论(4) 推荐(6) 编辑