博文

C++词汇解析集锦 编程开发人员必备(2007-11-21 22:09:00)

摘要:  1. 保留字   C++中,保留字也称关键字,它是预先定义好的标识符。见关键字的解释。   2.关键字   C++中已经被系统定义为特殊含义的一类标识符。C++中的关键字有: auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if static while asm _cs _ds _es _ss cdecl far huge interrupt near pascal class public private catch protected delete new template friend this inline throw try operator virtual overload(现不用)   3.标识符   对变量、函数、标号和其它各种用户自定义对象的命名。在C++中,标识符长度没有限制,第一个字符必须是字母或下划线,其后若有字符则必须为字母、数字或下划线。例如count2,_x是正确的标识符形式,而hello!,3th则是错误的。在C++中标识符区分大小写,另外标识符不能和C++中的关键字相同,也不能和函数同名。   4.声明   将一个标识符引入一个作用域,此标识符必须指明类型,如果同时指定了它所代表的实体,则声明也是定义。   5.定义   给所声明的标识符指定所代表的实体。   6.变量   某个作用域范围内的命名对象。   7.常量   常量是不接受程序修改的固定值,可以是任意数据类型。可以用后缀准确的描述......

阅读全文(2101) | 评论:0

[转] 何种代码布局风格为佳?(2007-11-17 18:33:00)

摘要:  Q: 何种代码布局风格为佳? A: 哦,这是个人品味问题了。人们常常很重视代码布局之风格,但或许风格的一致性要比选择何种风格更重要。如果非要我为我的个人偏好建立“逻辑证明”,和别人一样,我会头大的 :O) 我个人喜欢使用“K&R”风格,如果算上那些C语言中不存在的构造之使用惯例,那么人们有时也称之为“Stroustrup”风格。例如: class C : public B { public: // ... }; void f(int* p, int max) { if (p) { // ... } for (int i = 0; i < max; ++i) { // ... } }   这种风格比较节省“垂直空间”——我喜欢让尽量多的内容可以显示在一屏上 :O) 而函数定义开始的花括号之所以如此放置,是因为这样一来就和类定义区分开来,我就可以一眼看出:噢,这是函数! 正确的缩进非常重要。 一些设计问题,比如使用抽象类来表示重要的接口、使用模板来表示灵活而可扩展的类型安全抽象、正确使用“异常”来表示错误,远远要比代码风格重要。 [译注:《The Practice of Programming》中有一章对“代码风格”问题作了详细的阐述。] 原文地址:http://www.research.att.com/~bs/bs_faq2.html#layout-style......

阅读全文(2555) | 评论:0

[转] 我能防止别人从我的类继承吗?(2007-11-17 18:32:00)

摘要:  Q: 我能防止别人从我的类继承吗? A: 可以的,但何必呢?好吧,也许有两个理由: 出于效率考虑——不希望我的函数调用是虚的 出于安全考虑——确保我的类不被用作基类(这样我拷贝对象时就不用担心对象被切割(slicing)了)[译注:“对象切割”指,将派生类对象赋给基类变量时,根据C++的类型转换机制,只有包括在派生类中的基类部分被拷贝,其余部分被“切割”掉了。] 根据我的经验,“效率考虑”常常纯属多余。在C++中,虚函数调用如此之快,和普通函数调用并没有太多的区别。请注意,只有通过指针或者引用调用时才会启用虚拟机制;如果你指名道姓地调用一个对象,C++编译器会自动优化,去除任何的额外开销。 如果为了和“虚函数调用”说byebye,那么确实有给类继承体系“封顶”的需要。在设计前,不访先问问自己,这些函数为何要被设计成虚的。我确实见过这样的例子:性能要求苛刻的函数被设计成虚的,仅仅因为“我们习惯这样做”! 好了,无论如何,说了那么多,毕竟你只是想知道,为了某种合理的理由,你能不能防止别人继承你的类。答案是可以的。可惜,这里给出的解决之道不够干净利落。你不得不在在你的“封顶类”中虚拟继承一个无法构造的辅助基类。还是让例子来告诉我们一切吧: class Usable; class Usable_lock {
friend class Usable;
private:
Usable_lock() {}
Usable_lock(const Usable_lock&) {}
};
       
class Usable : public virtual Usable_lock {
// ...
public:
Usable();
Usable(char*);
// ...
};
       
Usable a;
       
class DD : publi......

阅读全文(2641) | 评论:0

[转] 我该把const写在类型前面还是后面?(2007-11-17 18:32:00)

摘要:  Q: 我该把const写在类型前面还是后面? A: 我是喜欢写在前面的。不过这只是个人口味的问题。“const T”和“T const”均是允许的,而且它们是等价的。例如: const int a = 1; // ok int const b = 2; // also ok   我想,使用第一种写法更合乎语言习惯,比较不容易让人迷惑 :O) 为什么会这样?当我发明“const”(最早是被命名为“readonly”且有一个叫“writeonly”的对应物)时,我让它在前面和后面都行,因为这不会带来二义性。当时的C/C++编译器对修饰符很少有强加的语序规则。 我不记得当时有过什么关于语序的深思熟虑或相关的争论。一些早期的C++使用者(特别是我)当时只是单纯地觉得const int c = 10;要比int const c = 10;好看而已。或许,我是受了这件事实的影响:许多我早年写的例子是用“readonly”修饰的,而readonly int c = 10;确实看上去要比int readonly c = 10;舒服。而最早的使用“const”的C/C++代码是我用全局查找替换功能把readonly换成const而来的。我还记得和几个人讨论过关于语法“变体”问题,包括Dennis Ritchie。不过我不记得当时我们谈的是哪几种语言了。 另外,请注意:如果指针本身不可被修改,那么const应该放在“*”的后面。例如: int *const p1 = q; // constant pointer to int variable int const* p2 = q; // pointer to constant int const int* p3 = q; // pointer to constant int原文地址:http://www.research.att.com/~bs/bs_faq2.html#constplacement......

阅读全文(2985) | 评论:0

[转] 宏有什么不好吗?(2007-11-17 18:31:00)

摘要:  Q: 宏有什么不好吗? A: 宏不遵循C++的作用域和类型规则,这会带来许多麻烦。因此,C++提供了能和语言其它部分“合作愉快”的替代机制,比如内联函数、模板、名字空间机制。让我们来看这样的代码: #include "someheader.h"
struct S {
  int alpha;
  int beta;
 };
如果有人(不明智地)写了一个叫“alpha”或者“beta”的宏,那么这段代码无法通过编译,
甚至可能更糟——编译出一些你未曾预料的结果。比方说:如果“someheader.h”包含了
如下定义: #define alpha 'a' #define beta b[2]那么前面的代码就完全背离本意了。 把宏(而且只有宏)的名称全部用大写字母表示确实有助于缓解问题,但宏是没有语言级保护机制的。例如,在以上例子中alpha和beta在S的作用域中,是S的成员变量,但这对于宏毫无影响。宏的展开是在编译前进行的,展开程序只是把源文件看作字符流而已。这也是C/C++程序设计环境的欠缺之处:程序员和编译器看到的源文件是不同的。 不幸的是,你无法确保其他程序员不犯你所认为的“愚蠢的”错误。比方说,近来有人告诉我,他们遇到一个含“goto”语句的宏。我见到过这样的代码,也听到过这样的论点——有时宏中的“goto”是有用的。例如: #define prefix get_ready(); int ret__ #define Return(i) ret__=i; do_something(); goto exit #define suffix exit: cleanup(); return ret__ void f() { prefix; // ... Return(10); // ... Return(x++); //... suffix; }   如果你是一个负责维护的程序员,这样的代码被提交到你面前,而宏定义(为了给这个“戏法”增加难度而)被藏到了一个头文件中(这种情况并非罕见),你作何感想?是不是一头雾水? 一个常见而微妙的问题是,函数风格的宏不遵守函数参数调用规则。......

阅读全文(2539) | 评论:0

[转] C++0x设计之路(2007-10-02 14:39:00)

摘要:C++0x设计之路  ————把握现在 展望未来                                                  [著] Bjarne Stroustrup                                                                 [译]firingme [译者注:原文地址:http://www.research.att.com/~bs/rules.pdf] 每隔一两天,我都会收到关于改进C++的e-mail建议。很多建议如果真的能够成为语言或者标准库的一部分将是一件不错的事情,会让很多程序员深受其益。当然,综合来看,这些建议有很多重复之处,因此,也可以说,在我提出的列表中仅有上百个建议而已——具体的数量取决于你对“相关建议”这个概念的定义。人们希望改进的语言特性的一份不完全列表在 http://www.research.att.com/~bs......

阅读全文(4197) | 评论:0

[转] C++ 0x 里的垃圾收集器(2007-10-02 14:37:00)

摘要:好像最近C++标准地下工会在公司附近开会,所以我们上班时偶尔可以看到工会成员矫健的身影。我们也近水楼台,得以听到关于C++0x进展的一些科普报告。上次Bjarne Stroustrup做了关于泛型编程的讲座后,Symantec实验室的Michael Spertus也做了一个关于C++ 0x里垃圾收集的讲座。Michael Spertus当年写出了IBM PC上最早的C编译器,也是C++ 0x里垃圾收集器的主要倡议人。       Michael从什么是GC开始讲起。三言两语后,谈到在C++ 0x里加入GC的动机。一是许多数据结构,对象,或者资源的生命期难以事先确定、静态管理。我们需要某种形式的动态管理技术。很多老大以为C++高手的标志之一是不需要GC。如果这样想,Unreal的Tim Sweeney就笑了。Unreal引擎里就大量使用GC。如果一个系统需要管理大量对象,要求高吞吐量,但可以容忍偶尔的系统延迟的话,GC是颇为不错的工具。所以3D/建模,2D图像处理等计算都可以用到GC。第二个理由非常有煽动力:帮助C++程序清除内存泄露。我们不必在C++里排斥人肉内存管理。问题是,人肉内存管理难以尽善尽美。大型系统里内存泄露几乎不可避免。每次泄露也不多,10来KB到几个MB。但积累起来,也就造成诸多问题。因为每次泄露量不大,也不像Java等基于GC的语言,“泄露”随时都在发生。所以可以通过定期执行GC来清除这些泄露,也不用消耗过多资源。Michael后来举了一个颇有说服力的例子:某电信公司的交换机,100多万行程序,有持续的内存泄露。每小时必须重启一次。使用GC后,内存泄露消失,交换机不用再定时重启。重启时系统堆上有大概200个线程,500MB内存。这样算来,每线程每小时泄露2.5M。每线程每分钟不过42KB。而每分钟收集42KB内存对系统根本不会有什么影响。最后实测下来,收集500MB不过需要两秒种。分摊到一个小时内,完全可以忽略不计。这样的GC应该叫LC—Litter Collector。还有一个例子是Michael向Mozilla浏览器里注入GC。每次用户操作使得GC回收大概10KB的内存,实在是小菜一碟。       Michael接着谈到C++ GC的发展。C++ GC已经......

阅读全文(2715) | 评论:0

[转] C++的进化:C++0x一瞥(2007-10-02 14:36:00)

摘要:摘要:C++标准委员会近年来一直在为下一代C++标准的制定而努力着,本文介绍了几个很可能成为下一代标准的新特性,包括generalized initialization,concept,move semantics,auto/delctype,让大家先睹为快。 1. 什么是C++0x     很简单,0x代表21世纪的第一个十年中的某一年,可能是07也可能是09,这要视标准出台的具体时间而定(但放心,不会是99),这也意味着新标准出台的时间不会太遥远了。 2. 新特性     这里我只打算从直观的角度介绍每一个新特性,关于每一个特性都可以在“C++ Standards Committee Papers”找到相应的论文。 2.1 Generalized Initialization     描述:支持将形如{1,2,3}的initializer作为参数进行传递
    意义:相信你一定写过这样的代码吧:         vector <int> v;
        v.push_back(1);
        v.push_back(2);
        v.push_back(3);     有了上述机制,只要给vector多加一个initializer为参数的构造函数,代码就可以简化为:         vector <int> v = {1,2,3}; 世界本应如此简单,不是吗。 2.2 Concept     描述:从语言层面支持STL的concept概念
    如下代码定义了一个EqualityComparable的conc......

阅读全文(2925) | 评论:0

Linux 下ACE的构建[转](2007-09-18 12:02:00)

摘要:Linux 下ACE的构建
1. 设置环境变量ACE_ROOT,命令如下:
“vi /etc/profile” ,在“export PATH USER….”后加入4行
 ACE_ROOT=/opt/ACE
 export ACE_ROOT
 LD_LIBRARY_PATH=$ACE_ROOT/aceLD_LIBRARY_PATH
 export LD_LIBRARY_PATH
完 成后将/etc/profile执行一次,命令:“chmod 555 /etc/profile”,“/etc/profile”。这样我们的ACE_ROOT就设置好了,可以用如下命令查看ACE_ROOT是否设置好了: “echo $ACE_ROOT” ,这个时候最好reboot启动一次linux。
2. 解压ACE.tar.gz包:
不 要自己手工将ACE.tar.gz包完全解开,特别强调不要完全解开,后面可以看到安装脚本会给我们解开它的;如果你手工解开全部,安装脚本将会将你的解 压缩目录删除的!我们要做的事就只是将ACE.tar.gz包中的ACE-install.sh安装脚本单独解出来,并对其修改。我们只要这一个文件就可 以。用mkdir建目录,如/home/my/ACE,然后将你的ACE.tar.gz放在此目录下(用cp命令拷贝或mv命令移动到此目录)。注意这个 目录将是你的一个存放ACE.tar.gz的目录,安装脚本会来这个目录找这个文件的,这个目录和ACE_ROOT是不一样的,且ACE- install.sh也提示不要将这两个目录设置成同一个目录。ACE_ROOT将是我们的安装目标目录。
3. 从ACE.tar.gz解压出单个文件ACE-install.sh,命令如下:
“tar –zxvf ACE+TAO+CIAO.tar.gz ACE_wrappers/ACE-install.sh”
解 好后,会出来一个新的子目录“ACE_wrappers”。此时可以先将ACE-install.sh移到外面的目录来:“mv /ACE_wrappers/ACE-install.sh .” “.”代表当前目录。当然ACE-install.sh在什么路径下是没什么影......

阅读全文(5570) | 评论:0

ACE的构建(VC++6.0环境)[转](2007-09-18 11:58:00)

摘要:ACE的构建(VC++6.0环境)
Windows下ACE的构建
1. 将ACE-5.5.zip解压到所需的安装目录,此处以E:\为例,解压后形成ACE_wrappers文件夹,因此ACE将会存在于ACE_wrappers\ace目录中。ACE_ROOT=E:\ACE_wrappers。
2. 在系统中新建ACE_ROOT环境变量,值设为 E:\ACE_wrappers。具体设置为:我的电脑->属性->高级->环境变量->新建
3. 在E:\ACE_wrappers\ace目录中创建一个头文件,命名为config.h,其内容为:
#include "ace/config-win32.h"(必选项)
#define ACE_HAS_STANDARD_CPP_LIBRARY 1 (MSVC自带的标准C++头文件)
#define ACE_HAS_MFC 1(与MFC一起使用)
#define ACE_NO_INLINE(取消函数内联从而减小静态库和运行码的大小)
#define ACE_AS_STATIC_LIBS(构建ACE的静态版本)
#define ACE_HAS_WINNT4 0(在Windows 9x/me上构建所需,在ACE中移掉一些WinNT/Win2K中特有的代码)
以上只需要添加前两项就可以了。
4. 在VC++中加载ACE的工程文件(ACE_ROOT \ace\ace.dsw),在release和debug两种编译方式下进行编译,得到相应的库文件(ACE.dll、ACE.lib 和 ACEd.dll、ACEd.lib),其中ACE.dll 、ACE.lib是由release版生成的,ACEd.dll、ACEd.lib是由debug版生成的。具体操作方法:运行VC++,选择Build ->Batch Build…,将ACE-Win32 Debug和ACE-Win32 Release全部选中,Rebuild All即可。如下图所示:

按照上面的方法可能只编译出ACE.dll 、ACE.lib库文件,具体原因还不详。按照下面的操作方法进行编译可以成功生成全部库文件。具体操作方法:Build->Set Active Configurati......

阅读全文(4045) | 评论:0