美文网首页
GeekBand C++ Week1 Notes

GeekBand C++ Week1 Notes

作者: 古来征战几人回 | 来源:发表于2016-05-10 22:04 被阅读0次

    GeekBand C++ Week1 Notes

    AOOP-面向对象编程

    1基础:C语言

    -变量variable

    -类型types

    -作用域scope

    -循环loops

    -流程控制

    -程序的编译和连结(如何运行)

    2目标编程习惯

    C++class

    Objectbased基于对象,单个类

    -Classwithout pointer members (complex)

    -classwith pointer members (string)

    Objectoriented面向对象,类之间的关系

    -inheritance继承

    -composition复合??

    -delegation委托??

    多态??封装??

    三个例子

    Complex.h complex-test.cpp

    String.h string-test.cpp

    Oop-demo.h oop-test.cpp

    C++历史

    B语言69,C语言72,C++83

    OO:java, C#

    C++98(1.0),C++03(TR1),C++11(2.0),C++14

    加的新特性讲的C++98??????

    C++语言(主要谈)C++标准库(庞大有用)

    书:C++ primer,C++ programming language

    C++standard library STL源码剖析

    B.头文件和类声明

    C语言和C++的比较

    C数据和函数的变量是全局的(没封装的坏处)

    C++数据和函数(方法)包在一起->建立很多对象

    类里面带指针和不带指针:

    不带指针:复数类,数据有实部和虚部,方法有加减乘除等

    带指针:字符串类,字符串是一个指针(另外分配空间存放字符串),方法有拷贝输出附加等。

    C++里面创建对象的方式

    C++代码基本形式:

    .h headfiles

    classes declaration

    .cpp

    #inlcude//<>从标准库里找

    #include”complex.h”//””从自己写的里面找

    ex.main()

    延伸名称不一定是.h和.cpp,不同平台

    C++ #include

    Cout << “I = “ << I <

    C#include

    Printf(“”)

    头文件的写法

    Complex.h

    #ifndef ___COMPLEX__

    #define __COMPLEX__//guard,防卫式声明

    //***********0,声明************//

    #include

    class ostream;

    class comlex;

    complex&

    __doap1(complex* ths, const complex& r);

    //*********1,类和声明********//

    class complex{

    }

    //********2,类,定义*********//

    complex::function …

    #endif

    第二次include时可以skip,防止重复代码DRY!

    1和2最重要,0是为了声明

    语法:复数类的声明,模板的应用

    template

    class complex{

    public:

    complex(T r = 0, T i = 0)

    :re(r), im(i)

    {}

    complex&operator += (const complex&);

    T real () const{return re;}

    T imag () const{return im;}

    Private:

    Tre, im;

    friendcomplex& __doap1(complex*, const complex&);

    }

    template是模板,可以改变类中的某些值?已定义的变量名,可以改变值?还是需要用方法改变。

    调用时,

    complex c1(2.5, 1.5);

    complex c2(2, 6);

    C. class的声明

    Complex& operator,没有大括号的方法内容,只是一个声明。

    Complex& operator += (constcomplex&);

    Inline函数:如果函数在class内定义完成是inline函数(内联函数)

    Double real () const {return re;}

    Double imag () const {return im;}

    Inline function会比较快比较好。但没有可能所有函数都是inline,函数太复杂无法inline???是不是Inline由编译器决定。。。上面两个函数在body内定义则为inline function但最后是不是真的是由编译器决定。

    Inline double

    Imag(const complex& x){

    Returnx.imag ();

    }

    后面出现的不在本体的部分也可以加inline?????

    Access level访问级别

    在类声明中可以分为public和private。

    什么要放在private?数据部分!为了封装起来,函数要看具体,还有protected。段落可以任意出现也可以交错,比如有好几个public。

    数据都应该放在private,函数内部处理可放在private,被外界调用可放在Public.

    构造函数,自动调用(constructor)

    complex (double r = 0, double I = 0)

    :re{r}, im(i)

    { }

    complex c1(2,1);

    complex c2;

    complex* p = new complex(4);

    -构造函数名称一定和函数名称相同

    -一定有参数

    -参数可以有默认值double r = 0,double I = 0

    -其他函数也可以有默认值!!!defaultargument

    -构造函数没有返回类型

    -赋值部分不要写在大括号里,利用只有构造函数可以用的语法

    : re (r), im (i)初值列,初始列和赋值re = r; im

    = I;一样的意义。

    数值的设定有两阶段,一个是初始化,一个是赋值,所以使用这种更为有意义??

    写在下面相当于放弃了初始化的阶段。

    -析构函数,不带指针的类多半不需要写析构函数

    构造函数可以有很多个。C++允许同一个函数多个出现,overloading因为输入参数不同

    有很多种初值的设定。

    Double real () const {return re;}

    Void real (double r) {re = r;}

    编译器编译后的实际名称可能是:

    ?real@Complex@@QBENXZ

    ?real@Complex@@ZARNABN@Z

    新加的构造函数

    complex () : re(0), im(0) {}

    这样是不行的!!!!!!!

    因为第一个构造函数有默认值

    complex c1;

    complex c2();

    编译器会发现两个构造函数都可以调用,所以会报错。

    -函数可以重载,输入类型不同

    -函数重载常常会发生在构造函数上。

    -像上面那样有默认值的如果两个同时可以调用就不行。

    D参数传递与返回值

    构造函数放在private区域会怎么样??

    此时complex c1(2,1);

    complex c2;就都不对

    什么时候要这样做?不允许被外界创造对象。

    设计模式Singleton

    class A{

    public:

    staticA& getInstance();

    setup(){}

    private:

    A();

    A(constA& rhs);

    }

    A& A::getInstance(){

    Static A a;

    Returna;

    }

    A::getInstance().setup();

    把构造函数写在private里叫Singleton

    函数部分

    double real () const {return re;}

    double imag () const {return im;}

    const的位置!!!!!

    这两个函数不改变值,class里的函数有改变数据内容和不改变数据内容,不改变数据内容的函数马上加const。不加的后果:

    complex c1(2, 1);

    cout << c1.real();

    cout << c1.imag();

    const complex c1(2,1);

    cout << c1.real();

    cout << c1.imag();

    下面的情况,complex是一个常数不可以改变,在用两个函数去调用的时候,如果函数里没写const说明函数可能会改data,编译器就会报错。Const可以用来修饰函数,可以用来修饰变量。

    参数传递,pass by value vs. pass by reference(to const)

    complex (double r = 0, double I = 0) passby value

    complex & operator += (constcomplex&); pass by ref to const

    operator << (ostream & os, constcomplex& x) pass by ref, pass by ref to const

    -pass by value是把整个值传过去,几个字节就几个字节。

    -传引用就相当于传指针那么快,形式很漂亮。

    Complex c1(2,1);

    Complex c2;

    C2 += c1;

    Cout << c2;

    -最好所有参数的传递都传引用,字节固定,四个字节。

    传引用,你改完会影响我。所以要看具体情况,但如果传过去只是为了速度,但不希望你改了会影响我,这时候可以用const.保证传给你后你不能改,你改了会影响我,此时如果传过去后被改了编译器会出错。

    -参数传递尽量都传引用。

    -如果想的细,比引用字节少,也可以传值。

    Operator << (ostream& os, constcomplex& x)

    第一个没有const说明允许改。

    返回值传递return by value vs. return reference(to const)

    coplex& operator += (constcomplex&);

    double real () const {return re;}

    double imag() const {return im;}

    friend complex& __doapl (complex*,const complex&);

    返回值尽量也传ref,在可以的情况下。

    Friend(友元)

    Friend complex& __doapl (complex*,const complex&);

    朋友可以来拿数据。

    Private外界不可以接触数据

    Inline complex&

    __doapl (coplex* ths, const complex&r){

    ths->re+= r.re;

    ths->im+= r.im;

    return*ths;

    }

    相同class的各个objects互为友元

    int func(const complex& param)

    {return param.re + param.im;}

    当类里的函数输入类型是该类的话可以直接拿里面的数据,为什么??

    看起来打破了封装,但是成立的。

    Complex c1(2,1);

    Complex c2;

    C2.func(c1);

    Class body外的各种定义definitions

    -数据一定放在private里

    -参数尽可能以ref来传,要不要加const看状况

    -返回值尽量也用ref来传

    -类的body里要加const的地方要加。

    -构造函数initialization

    list,冒号

    什么情况下不能return by ref呢?

    Inline complex&

    __doapl (complex* ths, const complex&r){

    ths->re+= r.re;

    ths->im+= r.im;

    return *ths;

    }

    加出来的结果是放在新创建来的地方还是放在已有的地方,如果是新生成的,在函数返回的时候就消失了,此时不能使用ref。除了这种情况都可以返回ref

    inline complex&

    complex::operator += (const complex&r){

    return __doapl(this, r)

    }

    E.操作符重载与临时对象

    头文件的防卫式声明,

    C++中允许对操作符进行重载,比如让加法支持复数。

    成员函数:this

    c2 += c1

    +=是一个二元操作符,编译器看到后会作用在左边上,

    inline complex&

    complex::operator += (this, constcomplex& x){

    return __doapl (this, r);

    }

    this是隐藏的部分,不写,所有的成员参数一定带有一个隐藏的参数,叫this,谁调用这个函数谁就是this,这里c2就是this,this是一个指针,编译器会自动把c2的地址传进来当做this,写代码的时候不必写也不能写this,不影响我们写代码,不能再参数列里写出来,但在函数中可以用。

    Return by ref语法分析

    传递者不需要知道接受者是以ref形式接受的。

    Inline complex&

    __doapl(complex* ths, const complex&){

    return *ths;

    }

    &写在后面和写在前面不一样,在后面是取得来的value的地址。

    +=是将后面的值加到前面,所以理论上一个+=运算符是可以返回void,但如果使用c3 +=

    c2 +=c1就会有问题,所以返回complex&更合理,可以进行多步操作。

    所有的上面都是头文件里面类的定义部分

    class complex{

    }

    下面是第二部分,成员函数和全域函数

    inline double

    imag(const complex& x){

    return x.imag();

    }

    操作符冲重载非成员函数

    c2 = c1 + c2;

    c2 = c1 +5;

    c2 = 7 + c1;

    编译器回去找调用哪个

    三种写法,所以要有三个函数

    inline complex

    operator + (const complex& x, constcomplex& y){

    return complex((real(x) + real (y), imag(x) + imag(y));

    }//复数加复数

    全域函数,没有this pointer???

    这三个函数都是返回value,为什么不用ref返回?

    他们返回的不能是ref,因为他们返回的必定是个local object,之前是右边加到左边,左边已经存在,现在需要先创建一个左边的空间来存放数据,离开该函数后这个地址就失效了。叫temp object。

    在上面函数中都没有定义complex,return complex();

    typename();

    这样的做法是创建临时对象,它的生命到下一行就结束了。

    比如

    complex();

    complex(4, 5);

    cout << complex(2);

    比较特殊,一般人少用,但标准库很常用。

    Negate

    Inline complex

    Operator + const complex& x){

    Return x;

    }

    inline complex

    operator – (const complex& x){

    returncomplex (-real (x), -imag (x));

    }

    区别由输入的参数不同来区别,

    negate返回的是一个新的东西,所以不能返回ref,但是上面的正好表示什么都不变,所以并没有产生新的结果,所以对于正号操作应该可以传回ref。

    ==

    cout << (c1 == c2);

    cout << (c1 == 2);

    cout << (2 == c1);

    考量输入有没有用ref,返回能否使用ref,

    共轭复数,实部相等,虚部符号相反,

    inline complex

    conj (const complex& x){

    return complex(real(x), -imag(x));

    }

    任何一个函数都可以有两种想法,全域函数或者成员函数。

    #include

    ostream&

    operator << (ostream& os, constcomplex& x){

    return os<< ‘(’ << real (x) << ‘,’ << imag (x) << ‘)’;

    }

    cout << conj(c1);

    对于output operator绝对不能写成一个成员函数

    cout << c1 << conj(c1);

    不能加const,因为ostream& os需要改变,所以不能加。按照道理,输出<<后面的值赋给前面后就没事了,所以可以返回值是void,但是当像上面一样连用后就不能返回void了。再去考虑返回的是by value还是by ref,发现返回的是原来的东西,所以用ref,再考虑要不要加const,发现改变了结果,所以不能加const。

    重点复习

    -构造函数的initialization:re(r), im(i)

    -函数要不要加const

    -参数的传递尽量考虑pass by ref,而且要不要加const要考虑

    -return的时候是ref还是value

    -你的数据几乎没有例外要放在private,而函数大部分要放在public,因为函数大部分要被外界调用。

    Complex类

    Week1总结

    在写一个date类的过程中,我的写过程:

    先声明宏定义,这个定义是为了防止重复引用头文件,在宏的名称命名规则上,系统内的宏一般以下划线或者双下划线开头,在我们自己定义宏的时候,尽量避免使用下划线开头,此处使用MYDATE

    然后,到了视频中所说的头文件的第0部分,主要有下面要定义的类的声明和全局函数的声明。较为简单。然后到了头文件的第2部分,类的声明和类内成员函数的声明,注意的地方富有:在写构造函数的时候,使用数据的初始化,具体原理为在构造一个新的函数时,有初始化和赋值两部分组成,写在此处的: re(r), im(m) { }是一个初始化的过程,可以将两部完整的分开,更加合理。后面的大括号里面可能是一些文件的读写过程。这个初始化的方法是类内独有的,注意不要在其他地方使用。在写类内成员函数的时候,需要注意的有输入是否传引用还是传值,包括返回值是传引用还是传值。规则是,当输入基本都可以传引用,但如果分的细在小于4字节的值传递时传值更加有效率,返回值当传回的值为新建的时候需要传值(临时建立,结束函数后即消失),原有的输入更改时传引用。除此以外,在函数前面要注意是否改变类内的值,如果没有改变要加const。具体还有如果将构造函数写在private里是singleton的设计模式,在某些只允许有一个对象存在时可以使用,使用singleton设计模式时要注意通过成员函数将对象传出。

    再到函数的第三部分

    重构成员函数和全局函数,第一返回值前面可以加inline表示当函数比较小时,具体定义方法在类内就定义好调用时可以增加效率,但具体能不能inline是编译器决定的.

    在写date函数时,有一个createpoints函数需要随机生成10个日期,在这个过程中我遇到了如何随机生成值得问题,使用了srand函数和rand()函数,每当使用srand设定一次种子,rand()函数重新生成会得到同样的值,导致一开始我在每次随机时都srand一次,得到了10个同样的值,后来只在一开始srand,每次rand()的值就不一样了。

    再是在排序的时候我使用了冒泡排序,当找到最小值后,我没有想就写了将一个日期等于另一个日期,编译后发现不对,对于新建立的类内没有定义=的用法,需要在类内增加一个对于date类的=用法或者设定一个新的方法可以将一个对象的值赋给另一个对象,后来我设计了setvalue的方法用于赋值。

    现在我遗留的问题有,在对complex类的例子里对于友元friend的设定可以是一个函数的意思是吗?因为以前只有接触过定义某个类是这个类的友元,则其private里的函数和值可以被其他类内直接调用,不知道我的理解对不对,即对某个函数定义为该类的友元,则在该全局函数里可以调用类内的private里的值或函数。

    在这第一个学期的学习里,知道了写头文件的时候的一些约定俗成的方法和段落,以及定义一个类和方法的一些规则。

    相关文章

      网友评论

          本文标题:GeekBand C++ Week1 Notes

          本文链接:https://www.haomeiwen.com/subject/zrbyrttx.html