Boolan C++面向对象高级编程(上)第一周笔记

本笔记仅供自己以后复习使用,记录以前没接触过或者对自己有启发的知识点,并做一定的思考与拓展


1.C++编程简介

主要介绍C++的发展历史,这个以前自己就看过,因此不再赘述。


2.头文件与类的声明

  • 头文件

为防止重复声明,头文件的防卫式声明格式如下:

#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_


思考与拓展:
为什么头文件要有防卫式格式?这个要从编译器如何对头文件进行预处理说起:

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

是不是只有这一种防卫式声明呢?除了课程中出现的这种,还有另外一种格式:

#pragma once
...//一些声明语句


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

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


3.构造函数

  • 初始化列表

一个变量的数值设定有两个阶段:一个是初始化,一个是后面的赋值操作,而初始化列表就是在初始阶段。如果放入大括号里面来做,结果相同,但相当于放弃了初始化,效率会差一些。

  • 构造函数放在private 
把构造函数放在private是不能被构造的,不能被外界调用。因为创建一个对象会调用构造函数,而private里的函数是不能被外界调用的,因此事不可以的。但确实有一种需求是放在里面:单例模式(Singleton)

class A
{
    public:
        static A& getInstance();
        setup() {...}
    private:
        A();
        A(const A& rhs);
        ... 
};

A& A::getInstance()
{
    static A a;
    return a;
}

使用:

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。


小结:

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

参考文章
http://blog.csdn.net/huangyizhi/article/details/50760522?locationNum=4
http://www.cppblog.com/szhoftuncun/archive/2007/10/28/35356.html
http://blog.csdn.net/monroed/article/details/50710161


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值