培养正规的、大气的编程习惯编程
1、C++简介函数
1,分类布局
C++分为基于对象和面向对象两种优化
基于对象是指简单的类定义,数据封装,没有类与类的联系,面对的是单一class的设计。又可细分为不带指针的类和带指针的类this
面向对象是指包含类与类之间的联系,面对的是多重class的设计。主要包括继承,复合,委托等。spa
2,历史和演化设计
1983年开发指针
重要版本:C++(98) 1.0 --> C++(03) TR1 --> C++(11) 2.0 --> C++(14)code
3,经典书籍对象
1,《C++ Primer》Fifth Edition ---Stanley B.Lippman ----> C++语言的发明者
2,《The C++ Programming Language》 Fourth Edition ---Bjarne Stroustrup -----> C++第一个编译器的做者
3,《Effective C++》Scott Meyers
4,《Effective C++》中文版 侯捷
5,《The C++ Standard Library》Second Edition --- Nicdlai M.Josuttiy
6,《STL源码剖析》侯捷
2、不成文规范
1,防卫式声明
对于大型程序每每有许多文件,在头文件相互包含时容易形成重复定义,采用如下的宏定义形式可避免重复定义的错误。
#ifndef __COMPLEX__ #define __COMPLEX__ // write your code #endif
2,头文件的布局--三段式
前置声明-类声明-类定义
3,类模板--避免了因为变量类型不一样编写大量冗余的代码
1 template<typename T> 2 complex<double> c1(2.5, 1.5) // complex类中的T都替换成double 3 complex<int> c2(2,6) // complex类中的T都替换成int
4,inline
1,简单的函数可在类体中直接定义,默认为inline
2,在类体外定义的函数须要显式声明inline
3,inline只是建议编译器优化,可是对于复杂的函数编译器没有能力优化
5,构造函数 complex(double r = 0, double i = 0):re(r),im(i){}
1,建立对象时,自动调用
2,参数可设置默认值
3,采用初值列初始化,比大括号中赋值效率高,构造函数特有初始化方式
4,没有返回值
6,建立对象的三种方法
1,complex c1(2, 1); // 采用传入的2,1进行初始化
2,complex c2; // 采用默认值0,0进行初始化
3,complex *p = new complex(4); // new申请一块内存空间,返回首地址,采用4,0进行初始化
7,不带指针的类多半不须要析构函数
8,构造函数能够有不少个--重载
反例--如下两个构造函数不能够同时声明,由于假如实例化一个对象complex c1;编译器不知道选择哪个构造函数
complex(double r = 0, double i = 0):re(r),im(i){} complex():re(0),im(0){}
9,构造函数放在private区域--singleton
1 class A 2 { 3 public: 4 static A& getInstance(); 5 setup(){...} 6 private: 7 A(); 8 A(const A& rhs); 9 ... 10 } 11 12 A& A::getInstance() 13 { 14 static A a; 15 return a; 16 }
10,常量成员函数
以下函数只是取数据而不会改变数据,须要加上const
double real() const {return re;}
若是不加const,说明使用者能够改变re,而使用者在建立对象时加const,说明是常量,不能够改变,先后矛盾,编译会不经过
1 const complex c1(2,1); 2 cout << c1.real(); 3 cout << c1.image();
11,参数传递 pass by value vs. pass by reference (to const)
1,尽可能pass by reference (to const)
2,pass by value可能数据量大,传输速度慢
3,pass by reference传输的是一个指针,传输速度快
4,传引用一旦被修改会影响到原变量,此时加const表示不能够修改
complex& operator += (const complex&);
12,返回值传递 return by value vs. return by reference (to const)
1,尽可能return by reference (to const)
13,友元--直接拿数据
1,缺点:破坏了封装性
2,优势:获取数据更快
3,疑问:第四讲26:50
侯杰老师讲友元函数破坏了封装性可是获取数据更快,因此doapl设置成了friend,我在想doapl若是只是在类的方法里调用的话,doapl设置成private是否是更好呢,既不破坏封装性又能够直接拿数据 (直接拿数据的意思是直接使用re,im)
Ans:因为其余地方也有可能用到
14,相同class的各个objects互为友元
1 public: 2 int func(const complex& param) 3 { return param.re + param.im } 4 usage: 5 { 6 complex c1(2,1); 7 complex c2; 8 c2.func(c1); 9 }
15,指导原则
1,数据都放在private里
2,参数尽量传reference
3,返回值尽量传reference
4,参数考虑是否加const
5,构造函数使用初始列
16,什么状况下可使用 return by reference
函数外部传入的变量返回可使用,函数内部定义的变量返回不可使用,关键点在于变量的做用域,函数内部的变量执行完成被销毁了就不存在地址了
1 inline complex& // 接受的是value的地址 2 __doapl(complex* ths, const complex& r) // 传递者无需知道接收者是以reference形式接受 3 { 4 ths->re += r.re; 5 ths->im += r.im; 6 return *ths; // 返回的是value 7 } 8 inline complex& 9 complex::operator += (const complex& r) 10 { 11 return __doapl(this, r); 12 }
17,操做符重载
1,成员函数--全部的成员函数都带着一个隐藏的参数this,指向调用者
此处返回值能够是void,可是不适用于c1 += c2 += c3
1 inline complex& 2 complex::operator += (const complex& r) 3 { 4 return __doapl(this, r); 5 }
2,非成员函数
1 c2 = c1 + c2; 2 inline complex 3 operator + (const complex& x, const complex& y) 4 { 5 return complex(real(x) + real(y),imag(x)+imag(y)); 6 } 7 c2 = c1 + 5; 8 inline complex 9 operator + (const complex& x, double y) 10 { 11 return complex(real(x) + y, imag(x)); 12 } 13 c2 = 7 + c1; 14 inline complex 15 operator + (double x, const complex& y) 16 { 17 return complex(x + real(y), imag(y)); 18 }
此处返回值类型绝对不能够是reference,因为不是外部传入的变量 建立临时对象complex(),下一行即失效---typename() 定义成非成员函数,int+c1调用的是double+c2的状况,int自动类型转换为double 当咱们把运算符定义成成员函数时,它的左侧运算对象必须是运算符所属类的一个对象 ----------------------------------------------------------------------------------------------------------------------- 内置类型里面+一般设计成非成员函数,+=一般设置成成员函数。咱们自定义类型的时候, +=和+模仿内置类型会符合用户一直以来的习惯