boolan面向对象编程 第一周笔记

来源:互联网 发布:手机破解软件资源 编辑:程序博客网 时间:2024/06/06 01:41
头文件与类的声明
头文件
为防止重复声明,头文件的防卫式声明格式如下:

#ifndef _COMPLEX_  
#define _COMPLEX_  
  
...//一些声明语句  
  
#endif  
头文件的基本布局格式如下:

#ifndef _COMPLEX_  
#define _COMPLEX_  
  
#include <cmath>  
  
class ostream;  
class complex;   //前置声明  
  
complex& _doapl (complex* ths, const complex& r);  
  
class complex  //类-声明  
{  
...  
};  
  
complex::function //类-定义  
#endif //_COMPLEX_  


思考与拓展:
为什么头文件要有防卫式格式?这个要从编译器如何对头文件进行预处理说起:
编译器将处理掉所有注释,以空格代替;
删除#define,展开所有宏定义;
处理条件编译指令#if、#ifdef、#elif、#else、#endif;
处理#include,展开被包含的头文件(直接将头文件复制进文件)
保留编译器需要使用的#progma指令等等。
如果有多份头文件均不进行防卫式声明,均包含了类似<iostream>这种内容很多的头文件,经过预处理以后的文件,即便自己只写了一行代码cout,它包含的代码量将是何其的庞大。这还不是最关键的问题,关键是头文件中定义了一个变量,那么多次包含该头文件之后,就会产生重复定义的问题。


是不是只有这一种防卫式声明呢?除了课程中出现的这种,还有另外一种格式:
[cpp] view plain copy print?
#pragma once  
...//一些声明语句  


两者的差别:
#ifndef的方式依赖于宏名字不能冲突,这不光可以保证同一个文件不会被包含多次,也能保证内容完全相同的两个文件不会被不小心同时包含。当然,缺点就是如果不同头文件的宏名不小心“撞车”,可能就会导致头文件明明存在,编译器却硬说找不到声明的状况
#pragma once则由编译器提供保证:同一个文件不会被包含多次。注意这里所说的“同一个文件”是指物理上的一个文件,而不是指内容相同的两个文件。带来的好处是,你不必再费劲想个宏名了,当然也就不会出现宏名碰撞引发的奇怪问题。对应的缺点就是如果某个头文件有多份拷贝,本方法不能保证他们不被重复包含。当然,相比宏名碰撞引发的“找不到声明”的问题,重复包含更容易被发现并修正。


方式一由语言支持所以移植性好,方式二 可以避免名字冲突。
到底选哪一种呢,这是个兼容性和效率的问题。


3.构造函数
初始化列表
一个变量的数值设定有两个阶段:一个是初始化,一个是后面的赋值操作,而初始化列表就是在初始阶段。如果放入大括号里面来做,结果相同,但相当于放弃了初始化,效率会差一些。
构造函数放在private 
把构造函数放在private是不能被构造的,不能被外界调用。因为创建一个对象会调用构造函数,而private里的函数是不能被外界调用的,因此事不可以的。但确实有一种需求是放在里面:单例模式(Singleton)
[cpp] view plain copy print?
class A  
{  
    public:  
        static A& getInstance();  
        setup() {...}  
    private:  
        A();  
        A(const A& rhs);  
        ...   
};  
  
A& A::getInstance()  
{  
    static A a;  
    return a;  
}  


使用:
[cpp] view plain copy print?
A::getInstance().setup();  
对不改变数据内容,只是取出来的,加const


4.参数传递及返回值
参数传递:pass by value or pass by reference(to const) 
可看出有三种情况,先看pass by value:传递value,就是复制数据整包的传过去,把复制的参数压到函数的栈里面去。很显然效率低,因此尽量不要pass by value,而应该尽量使用pass by reference。(C语言中有传递指针的),其实引用在底层就是指针实现的,所以说pass by reference传递快,因此尽量使用引用传递。而如果传递的数据不希望被更改就使用pass reference to const。
pointer参数和reference参数的重要差异:传入的pointer可能为0,因此必须得先检查确定其值是否为0,而reference则必定会代表某个对象,所以不须做此检查
返回值传递return by value vs return by reference(to const)
C++的效率高,在每一个影响效率的小节上应该注意,返回值的传递也尽量return by reference(当然在可以的情况下),有些情况是不可以的,下面看这种情况。
一个函数的操作结果放在什么位置?如果必须创建一个位置供他放,那返回的就是新的local对象,这时候不能return by reference,因为local 变量,函数一结束就已经死亡了,这样就会出错。若放在函数某个位置,那就可以传递reference。


5.操作符重载
操作符重载-成员函数
所有的成员函数函数都带着一个隐藏的参数this指针。
temp object临时对象
typename()就是要创建临时对象,对于临时对象的生命周期:下一行就结束了。创建临时对象的用法在创建stl中很常见。 
注意对于这些临时对象绝不可return by reference。因为它们是local object。




小结:
头文件防卫式声明;
构造函数的初始化问题;
数据尽量放在private里面;
传递参数:尽量用 pass by reference;
传递返回值:若不是local object,尽量用return by reference;
若是函数调用不用改变参数,则加上const;