Participants:LF,HZP,CPP,ZY<!----><o:p></o:p>
Date:<!----><st1:chsdate isrocdate="False" month="9" islunardate="False" day="16" w:st="on" year="2008">08-09-16</st1:chsdate> 7:20PM<o:p></o:p>
Recorder: CPP,ZY<o:p></o:p>
参考文献:<o:p></o:p>
1、《effective C++》2nd Edition,Scott Meyers etc.<o:p></o:p>
2、《C++程序设计教程》,钱能<o:p></o:p>
3、《高质量C++C编程指南》,林锐<o:p></o:p>
4、http://keith.ecjtu.com/article.asp?id=319<o:p></o:p>
<o:p> </o:p>应大家的要求,今天晚上开始了我们的第一次讨论会。<o:p></o:p>
主要是针对C++里面的一小撮问题展开的,这里我给出讨论的概要:<o:p></o:p>
1、关于优先级与结合性;(这里要重点“批”一下HZP和ZY,正号和加号都分不清的家伙…)(顶)<o:p></o:p>
2、#define \inline\const(顺便涉及到inline 和 virtual的连用问题);<o:p></o:p>
3、const的作用(包括修饰类的成员函数,成员函数返回值,成员函数的参数列表,数据成员);<o:p></o:p>
4、重载、覆盖(重写/改写,实现多态)以及隐藏的区别;<o:p></o:p>
5、构造函数和析构函数<o:p></o:p>
6、关于虚拟函数、虚基类及多继承<o:p></o:p>
1、优先级口诀:(除了标明是右结合外,都是左结合)<o:p></o:p>
括号成员第一;//[]、()<o:p></o:p>
全体单目第二;//比如++、--、+(正号)、-(负号)、指针运算符* & 右结合<o:p></o:p>
乘除余第三;//取余 左结合<o:p></o:p>
移位五,关系六;<o:p></o:p>
等于不等排第七;<o:p></o:p>
位与亦或和位或;//&、 ^、|<o:p></o:p>
逻辑或跟与;//&&、||<o:p></o:p>
条件高于赋值;//注意的是赋值运算符很多,包括= 、*=、 /=、 +=、 -= 、|=、 <<=和>>= 二者都是右结合<o:p></o:p>
逗号排最后。<o:p></o:p>
上面是C中的规则,而C++由于引入了一些新的运算符,因此,有些出入,如表1:
表<st1:chmetcnv tcsc="0" hasspace="True" sourcevalue="1" numbertype="1" negative="False" unitname="C" w:st="on">1 C</st1:chmetcnv>++ 运算符优先级列表<o:p></o:p>
见两个例子:<o:p></o:p>
(1) int x=1,y=0;<o:p></o:p>
!x&&x+y&&++y;<o:p></o:p>
加括号确定优先级的方法
当多个优先级不同的运算符在一起时,为了不混淆,可以先加上括号,这样就分出层次了,相同层次的考虑结合性问题,当确定下来先算那块时,再往这块里面深入。例如上面的例子,我们可以这样加上括号:从左向右看,由于!比&&优先级高,所以有(!x),又由于&&比+优先级低,所以有(x+y),而++优先级高于&&,所以(++y)。这样整个式子就变成了:(!x)&&(x+y)&&(++y),最外层的是两个&&运算,由于&&的结合性是从左至右,所以上式可看成:A&&B&&C,先计算A,再计算B,最后算C.由于x=1,则!x就为假,后面的就不需要再算了,整个语句的值为假。执行完后,y的值没变,还是0.
所以碰到不清楚先算谁后算谁时,先加个括号看看,就明白了先后次序。<o:p></o:p>
(2)给语句c=a>b?a:b;加括号。此语句有三个运算符:=、>、? :,应该怎样加括号呢?<o:p></o:p>
第一种方案:c=((a>b)?a:b);
第二种方案:c=(a>(b?a:b));
第三种方案:(c=a)>(b?a:b);
应该是那一种呢?按照运算符优先级的高低顺序,>优先级高于=,所以不可能把(c=a)括起来。而>优先级高于? :运算符。所以也不可能把(b?a:b)括起来。因此,第一种答案正确。<o:p></o:p>
<o:p> </o:p>
2、尽量以const和inline取代#define<o:p></o:p>
尽量以编译器取代预处理器或许更好,因为#define通常不被视为语言本身的一部分。<o:p></o:p>
#define导致的结果就是程序内所使用的名称并未出现于符号表之中。可以改用常量来声明。<o:p></o:p>
若是需要一个class专属常量,即将这个常量的scope局限于class 之内,必须让它成为一个member,而为了确保这个常量至多只有一份实体,则必须让他成为一个static member,例如:
class GamePlayer{<o:p></o:p>
private:
static const int NUM;//仅仅是个声明而非定义<o:p></o:p>
…<o:p></o:p>
};<o:p></o:p>
必须在类定义文件中定义该类成员:const int GamePlayer::NUM=5;<o:p></o:p>
另一个误用#define指令的常见例子是,以它来实现宏——看起来像函数,却又不会带来函数调用所需的成本。经典例子就是计算两数的最大值:<o:p></o:p>
#define max(a,b) ((a)>(b)?(a) : (b))<o:p></o:p>
即使加上了小括号,还是会发生一个可怕的动作:<o:p></o:p>
int a=5,b=0;<o:p></o:p>
max(++a,b);//a被累加两次<o:p></o:p>
max(++a,b+10);//a被累加一次<o:p></o:p>
这时,我们可以使用inline函数,既可以得到宏带来的高效率以及函数带来的可预期行为和类型检验。例如:<o:p></o:p>
inline int max(int a, int b) {return a>b?a:b; }<o:p></o:p>
这与前述宏并不完全相同,因为这个版本的max只接受int类型参数,不过,template可以修正这一问题,这里by reference相比by value可以获取更高的效率。<o:p></o:p>
template<class T><o:p></o:p>
inline const T& max(const T& a, const T&b)<o:p></o:p>
{return a>b?a:b; }<o:p></o:p>
3、const的作用<o:p></o:p>
(1)修饰类的成员函数时:<o:p></o:p>
即在成员函数声明时将const置于成员函数参数列表后分号前,代表它不能对类的数据成员进行修改,但是有一个例外,就是当数据成员前有mutable修饰时,它是可以被该函数修改的;<o:p></o:p>
(2)修饰成员函数返回值及函数参数时:<o:p></o:p>
意即被修饰的量是不可被修改的,前者意味着在成员函数返回后得到的值不可被更改,后者意味着不能在函数体内对参数进行变动,只能读取它;<o:p></o:p>
(3)对于类中的const常量,它只在某个对象生存期内是常量,而对于整个类而言却是可变的,因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。<o:p></o:p>
不能在类声明中初始化const数据成员,只能在类构造函数的初始化表中进行,例如:<o:p></o:p>
class A<o:p></o:p>
{…<o:p></o:p>
const int SIZE=100;//错误,企图在类声明中初始化const数据成员<o:p></o:p>
int array[SIZE];//错误,位置的SIZE<o:p></o:p>
};<o:p></o:p>
应该是:<o:p></o:p>
class A <o:p></o:p>
{<o:p></o:p>
A(int size);<o:p></o:p>
const int SIZE;<o:p></o:p>
};<o:p></o:p>
A::A(int size):SIZE(size){<o:p></o:p>
…<o:p></o:p>
}<o:p></o:p>
若要建立在整个类中都恒定的常量,需要用枚举常量来实现,例如:<o:p></o:p>
class A{<o:p></o:p>
enum{SIZE1=100,SIZE2=200};//<o:p></o:p>
int array1[SIZE1];<o:p></o:p>
int array2[SIZE2];<o:p></o:p>
};<o:p></o:p>
枚举常量不会占用对象的存储空间,它们在编译时被全部求值。枚举常量的缺点是:它的隐含数据类型是整数,其最大值有限,且不能表示浮点数.(PI=3.14159)<o:p></o:p>
<o:p> </o:p>
4、重载(overload)、覆盖(override)以及隐藏<o:p></o:p>
本来是讨论多态的,但是我们又讲到了重载这个概念,对于一个类中的成员函数,其被重载的特征:<o:p></o:p>
(1)相同的范围(同一个类中);<o:p></o:p>
(2)函数名相同,参数列表不同,返回值类型可相同也可不同。<o:p></o:p>
覆盖是指派生类函数覆盖基类函数,其特征:<o:p></o:p>
(1)不同范围;<o:p></o:p>
(2)函数名字相同,参数列表相同,<o:p></o:p>
(3)基类必须要有virtual关键字。<o:p></o:p>
除覆盖外,所有同名的基类函数与子类函数都属于隐藏,下面是一个例子,讲得比较清楚,也点出了问题的本质:<o:p></o:p>
- class Base
- {
- public:
- Base();
- virtual ~Base();
- public:
- virtual void f(float x)
- {
- cout << "Base f(float)" << x <<endl;
- }
- void g(float x)
- {
- cout<< "Base g(float)" << x <<endl;
- }
- void h(float x)
- {
- cout<< "Base h(float)" << x <<endl;
- }
- };
- 派生类:
- class Derived:public Base
- {
- public
分享到:
相关推荐
在IT行业中,会议记录是团队协作和项目管理中不可或缺的一部分,尤其对于C++开发者或团队而言,有效的会议记录能够确保信息传递的准确性和效率。以下将详细解释如何编写符合标准的C++会议记录,以及其相关知识点。 ...
该文档为 C++11 标准的早期草稿版本,旨在为 C++ 开发者提供全面的更新指南,帮助理解并掌握 C++11 的新特性和改进之处。 #### 三、文档主要内容 - **1. General 一般性介绍** - **1.1 Scope 范围**:定义了 C++...
- **版本状态**: 当前版本为0.6版,作为开源项目的一部分,它处于不断发展和完善之中。 - **许可协议**: 该项目采用了MIT许可证,并规定贡献者需签署贡献者许可协议。 - **目标受众**: 面向所有对C++感兴趣的开发者...
《Effective C++》、《More Effective C++》以及《Exceptional C++》都是经典之作,它们涵盖了大量关于如何写出高效、可维护代码的最佳实践。 ### 24. 学习并理解C++的内存管理机制 C++允许程序员直接操作内存,这...
接下来,我们讨论日志记录的基本概念。日志通常包含时间戳、日志级别(如DEBUG、INFO、WARNING、ERROR)、发生事件的模块或函数名,以及实际的日志消息。日志级别用于区分重要性,方便在排查问题时快速定位关键信息...
- **《C++沉思录》**:作者通过一系列的思考题引导读者思考C++编程的各种细节,有助于提高解决问题的能力。 - **《STL源码剖析》**:深入研究STL的实现原理和源代码,非常适合想要深入了解标准库内部机制的人。 - **...
首先,我们来讨论C++在数据库管理系统中的应用。C++是一种强大的、面向对象的编程语言,具有高效性、灵活性和丰富的库支持。在构建医院门诊管理系统时,C++可以用于实现数据结构、用户界面和系统逻辑。通过C++的类和...
在技术细节上,C++标准库构成了C++20标准的约四分之三,但论文的重点是语言特性及其支持的编程技术。标准的演变旨在通过逐步的改变保留C++的本质,同时简化其使用,改进泛型编程,更好地支持编译时编程,扩展对并发...
相比之下,《C++变成死相》可能更多地关注于语言的细节和技巧,但缺乏对于编程思想的指导。 #### 3. 看《The C++ Programming Language》和《Inside The C++ Object Model》,不要因为他们很难而我们自己是初学者...
总的来说,"C++实现的PC 游戏编程之中国象棋"项目涵盖了C++编程基础、面向对象设计、游戏规则逻辑、决策算法、图形用户界面和机器学习等多个方面的知识。通过这个项目,开发者不仅可以提升编程技能,还能深入理解...
5.7 **注释**:定义了C++中可用的注释风格,帮助开发者记录代码。 5.8 **头文件名**:规定了头文件命名的规则和约定。 5.9 **预处理数字**:描述了预处理器如何处理数字常量。 5.10 **标识符**:定义了标识符...
VCL组件库使得开发者能够通过拖放方式快速构建用户界面,而无需关心底层的Windows API细节。此外,还会有涉及事件驱动编程模型的讨论,帮助读者理解如何响应用户操作。 C++ Builder 5支持面向对象编程,书中的章节...
7. **总结与反思**:总结实验过程中的收获,分析项目中的不足之处,以及可能的改进方向,如增加加密以保护通信安全,支持更多用户同时在线,或者添加图形用户界面(GUI)以提供更好的用户体验。 通过这个项目,...
在IT行业中,C++是一种强大的、面向对象的...不过,由于该文件未提供具体内容,这里只能基于“Meter改进 C++”这个主题进行一般性的讨论。对于实际的代码实现和改进细节,需要查看文件内容才能给出更具体的分析和建议。
接下来,我们讨论C++类的封装。封装是面向对象编程的核心概念,它将数据和操作数据的方法绑定在一起,形成一个独立的实体——类。在这个LZSS压缩算法的实现中,类可能包含以下组成部分: 1. **成员变量**:可能包括...
当然,实际的项目可能还需要考虑更多细节,如安全性、性能优化等,但以上的讨论已为我们提供了一个基本的架构和思路。在实践中,不断迭代和完善,才能真正打造出一个高效、稳定的网上拍卖系统。
下面将详细讨论这个系统可能涉及的C++知识点、数据库操作和员工工资管理的基本概念。 1. C++基础知识: - 类与对象:C++是一种面向对象的编程语言,员工工资管理系统会涉及到类的设计,如`Employee`类用于封装员工...
在本篇文章中,我们将深入探讨如何使用C++获取特定软件如360的安装路径,并且讨论如何通过调整代码来适应其他软件。 首先,我们要明白操作系统对软件安装路径的管理和访问方式。在Windows系统中,通常每个软件都有...