[BoolanC++微专业] Week1笔记

来源:互联网 发布:java飞机大战 编辑:程序博客网 时间:2024/05/09 09:44

Boolan网C++微专业笔记第一周:侯捷老师从complex类开始入手,主要介绍有关类的各种语法,结合侯捷老师的课程和我之前对C++语言的了解,做笔记如下:

     一、以良好的方式编写C++ class。

     侯捷老师将C++类的编写划分为两种:

             其一为object base: 即为面对单一class的设计。

                    大致上分为两类:包含指针的类和不包含指针的类。在我目前的水平看来,两个类最大的区别就在于对内存的管理上不包含指针的类并不需要时刻注意管理内存,释放内存,但是包含指针的类一定要记得有new必有delete。

             其二为object oriented: 即为面向多重classes的设计,主要研究的式class与class之间的关系。

                     继承(inheritance)

                     复合(compostion)

                     委托(delegation)

    二、C++语言的演化。

    B[1969]--->C[1972]--->C with Classes[1979]--->C++[1981]

    三、类。

    类的基本思想是数据抽象(data abstraction)和封装。数据抽象是一种依赖于接口(interface)和实现(implemeion)分离的编程以及设计。

    常常听到有人说这句话:“万物皆对象”,有人说这句话的意思是C++中的一切都可以看做对象,但是我认为这句话的意思应该理解现实世界的所有东西,都可以看错是对象(object)对它的一种抽象,比如现在在我眼前的笔记本,它的硬件基础,就是他的属性(arributes),我通过IO与它进行的交互,便是他的行为(behavior),然后相同的一种种类的电脑具有同一性(indentity)。而电脑,在抽象中,即可以看作一个computer类。

    四、C++代码的基本形式。

    在初级阶段,一个C++工程,一般包括以下三种文件:

    head.h:头文件,类以及所有函数的声明在此。

    head.cpp:头文件的实现文件。 

    head.cpp与head.h链接起来便是一个小小的库

    main.cpp:源文件

    main.cpp与head.cpp通过include与头文件链接。

    include<>在 计算机本地库里进行搜索,再搜索用户自己实现的库。

    include""在用户自己实现的库种进行搜索。

    头文件的写法:

   

#ifndef __HEAD_H_            //防止多次包含同样的头文件#define __HEAD_H_class myClass;               //类的声明type myFun();                //函数的声明class myClass                //类的定义{
//
//};#endif                       //回应前方的 #ifndef 
   
    在头文件种最好包含前置声明,不然在编程过程种极易出现错误,比如如下程序:

int  myFunc(myClass myclass);class myClass{////};
     因为在生成myFunc()时编译器并没有发现myClass这个类型的数据声明存在,所以会报错。
   
    内联:
    函数在类内定义时,自动转成内联的候选人。
    inline只是向编译器发出的一个请求,编译器可以选择忽略这个请求。
    一般来说,inline用于优化规模小,流程直接,频繁调用的函数,而且很多编译器并不支持内联嵌套函数。内联函数主要是抵消了函数调用时的开销,但是如果将内联函数全部展开的开销大于函数调用的开销,编译器便会自动忽略内联的请求。
    内联函数通常定义在头文件中。

    封装:
    定义在public说明符后的成员在整个程序内可以被访问,public成员定义类的接口。
    定义在private说明符号后面的成员可以被类的成员函数访问,但是不能被使用该类的代码访问,private部分封装了类的实现细节。  
    一个类可以包含0个或者多个访问说明符,而且对于某个访问说明符能出现多少次也没有严格限定。每个访问说明符指定了接下来的成员的访问级别,其有效范围直到出现下一个访问说明符或者到达类的结尾为止。
    一个类可以用struct或者class进行定义,区别便是struct的默认访问权限为public,而class的默认访问权限为private。

   友元:
   类可以允许其他类或者函数访问它的非共有成员,方法是令其他类或者函数称为它的友元。如果想把一个函数作为它的友元,只需要增加一条以friend关键字开始的函数声明语句即可。
   友元函数如果定义在类的内部,则其是隐式内联的,相同种类的类互为友元。

    构造函数:
    每个类都分别定义了它的对象被初始化的方式,类通过一个或者几个特殊的成员函数来控制其对象的初始化过程,这些函数叫做构造函数(constructor)。构造函数的任务是初始化对象的数据成员,无论何时,类被创建,就会执行构造函数。
    在c++11中引入了列表初始化。
    列表初始化有以下几点优势:
    1)在类中存在常量时,常量只能初始化,不能赋值。
    2)类成员中存在引用,同样只能初始化,不能赋值。
    3)类成员在基类或者成员类中没有定义默认构造函数。
    另外使用列表初始化可以提高效率。
    构造函数也可以存在于private区域中,这种写法被称为单例(singleton)模式。
    它的主要特点不是根据用户程序调用生成一个新的实例,而是控制某个类型的实例唯一性,通过下图我们知道它包含的角色只有一个,就是Singleton,它拥有一个私有构造函数,这确保用户无法通过new直接实例它。除此之外,该模式中包含一个静态私有成员变量instance与静态公有方法Instance()。Instance()方法负责检验并实例化自己,然后存储在静态成员变量中,以确保只有一个实例被创建。
 
优点:
    1、实例控制: 单例模式会阻止其他对象实例化其自己的单例对象的副本,从而确保所有对象都访问唯一实例。
    2、灵活性: 因为类控制了实例化过程,所以类可以灵活更改实例化过程。

缺点
    1、开销: 虽然数量很少,但如果每次对象请求引用时都要检查是否存在类的实例,将仍然需要一些开销。可以通过使用静态初始化解决此问题。
    2、可能的开发混淆:使用单例对象(尤其在类库中定义的对象)时,开发人员必须记住自己不能使用new关键字实例化对象。因为可能无法访问库源代码,因此应用程序开发人员可能会意外发现自己无法直接实例化此类。
    3、对象生存期:不能解决删除单个对象的问题。在提供内存管理的语言中(例如基于.NET Framework的语言),只有单例类能够导致实例被取消分配,因为它包含对该实例的私有引用。在某些语言中(如 C++),其他类可以删除对象实例,但这样会导致单例类中出现悬浮引用。
   
    const修饰符:
    const修饰类的成员函数,则该成员函数不能修改类中任何非const成员函数。一般写在函数的最后来修饰。

class A
{
// 函数后面加 const表示函数不可以修改class的成员。换而言之,这种函数不能改变this实例的任何数据
void function()const; //常成员函数, 它不改变对象的成员变量. 也不能调用类中任何非const成员函数。
}
    对于const类对象/指针/引用,只能调用类的const成员函数,因此,const修饰成员函数的最重要作用就是限制对于const对象的使用。

    const常量与define宏定义的区别

    1) 编译器处理方式不同
    define宏是在预处理阶段展开。
    const常量是编译运行阶段使用。

    2)类型和安全检查不同
    define宏没有类型,不做任何类型检查,仅仅是展开。
    const常量有具体的类型,在编译阶段会执行类型检查。

    3)存储方式不同
    define宏仅仅是展开,有多少地方使用,就展开多少次,不会分配内存。
    const常量会在内存中分配(可以是堆中也可以是栈中)。
    在可以使用const的地方使用const可以大大提高程序的健壮性,和对象设计的封装性。
   
    传参:
    在可以传入引用的时候,就应该传入引用,因为pass by reference可以节省一次拷贝的开销,并且可以节约一个拷贝的空间。
    如果害怕函数修改了不应该修改的引用参数,那么可以在引用前加const进行修饰。
    运算符重载时候也是可以传入应用就最好传入引用。但是存在一个例外:
    在重载 '<<' '>>'运算符时
   
ostream &operator(ostream &os,myClass a);
     由于我们没有办法复制一个ostream对象,所以我们必须传入一个引用。
     在运算符重载时,可以声明为一个成员函数,也可以声明为一个友元。
     双目运算符最好使用友元来进行声明,以complex为例
   
complex&operator + (const complex& x, const complex& y);complex&operator + (const complex& x, double y);complex&operator + (double x, const complex& y);
    此时由于rhs和lhs非常灵活,所以需要重载多个函数来实现。

    临时对象:
    1)用构造函数作为隐式类型传递函数时,会创建临时对象。
    2)建立一个没有命名的非堆对象时,会创建临时对象。
    3)函数返回一个对象值时,会产生一个临时对象。

   


0 0
原创粉丝点击