C++学习 —— 住着魔鬼的细节

  13周的C++课程转眼就学完了5周,C++的标准基本上已经覆盖到了。再加上coding了上百行,总算是对C++有了一个基本的了解。接下来的学习会是关于STL的,因此在此对目前所学作一个小的总结。ios

  the devil is in the detail这是我最大最大的体会。由其是对于这种称之为标准的内容而言。更是如此。c++

一、赋值,引用,指针

  这三个概念是不少编程语言里面共有的,为了实现c++的高效率,这3板斧更是被发挥的淋漓尽致。总结一下,能够分为两种状况:【传】【返回】。编程

  【传】赋值的意思就是对变量进行复制  fun(int a), fun(5)。 matlab 里所有都是这样的调用,matlab 并不能传引用。这样作的好处是函数不会修改传入值,坏处是须要对传入的参数进行复制,若是参数很大(e10的点云),那么复制会有很大开销。编程语言

  【传】引用的意思是将变量的引用传入,好比 fun(int & a) , int b; fun(b)。这样的作法能够在函数中改变b的值。好处是直接传了地址,不须要复制开销,坏处是不利于变量保护。ide

  【传】指针和传引用相似,通常状况下,指针是一种很丑的参数,可是有的时候又不得不以指针做为参数。好比点云,每每点云的规模是动态的,内存也是动态分配的,因此不少点云处理函数的参数都是PointCloud<PointXYZ>::ptr,传指针是会改变指针所指向的内容的。函数

 

  【返回】值的意思是函数返回一个值,每每是 a = fun(b),被返回的值只能作右值。学习

  【返回】引用的意思是返回一个变量,这个变量能够有值,也能够未被初始化。它是能够做为左值的,好比 a.getobj() = createobj(A). 或者 ostream & operator <<(ostream & o){return o;  } cout<<MY_OBJ<<endl; this

  【返回】指针,返回一个指针也是无奈之举,好比输入的是一个点云,返回它的分割子集。spa

  总而言之,返回引用多半是为了作左值,返回指多半是由于有开销上的顾虑。设计

 

二、const 与数据保护

  const 有三种用法,分别是和数结合,和指针结合,和函数结合。

  【和数结合】和数结合的状况很是单纯,意思就是这个变量不能改了。 int c, const int a =5; const int & b = c; 这样的状况下a = 1, b= 1都会报错,若是想要b = 1,能够令c = 1;

  【和指针结合】和指针结合的状况有点点复杂,分两种 const int * p = & c; 表示常int,这是意思是c的值不能经过p 来修改,和上面的常引用是同样的意思!! int const *p = & c 则表示常*p,意思就是p不能指向其余数据。

  【和函数结合】和函数结合要更复杂那么一点点。分两种状况,fun(const int & a),表示a 不能被修改。fun(int a) const{},const 修饰{}——常成员函数,表示成员函数不容许修改为员变量。常对象只能调用这种常成员函数。

 

三、构造与析构

  构造与析构是面向对象的路子。主要是构造函数有一点复杂,分缺省构造,普通构造,拷贝构造。

  【缺省构造】若是咱们不写构造函数,那么会自动生成缺省构造函数。可是一旦写了,那么就没有缺省构造函数了。若是你想要没参数的构造函数,要么用缺省值假装,要么本身写上 myclass(){}。建议后者,有时候不记得搞了缺省值会出事的。

  【普通构造】构造函数的做用是初始化成员变量,若是成员变量是私有的,那极可能只有这么一次机会初始化。

  【拷贝构造】拷贝构造是最啰嗦的,它有两种调用形式:一、myclass b ;  myclass a(b); 二、myclass a = b。 第二种看似用了操做符 = ,实际不是的,它调了拷贝构造函数,而不是操做符重载。若是你重载了=,最好别有二义性。

  【析构函数】析构函数最重要的是,若是用new 申请了变量,那么必定要在析构函数里delete []。固然,若是用boost 的 智能指针,能够不用手动释放。

 

四、操做符重载

  操做符重载仍是比较好理解的,记好一个细节,左值要返回引用。

 

五、继承

  继承是 is 的操做,若是一个类继承了其夫类,那么子类的对象,在内存里会有父类的全部成员变量!而且自动得到父类全部的成员函数。不过得到的成员函数只能操做内存里父类的那些成员变量了。

  设计继承最重要的是子类必须得到父类全部的性质。若是父类有一个行为是子类不须要的,那么就算设计的很差了。

  子类中比较有难度的是构造函数的设计,由于要对内存里父类的那些成员变量赋值,因此其构造函数要写成以下:son(int a,int b,int c):father(a,b),c_(c){}。直接用父类的类名,来完成成员变量的赋值。一个简单的继承例子以下:

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdlib>
 4 using namespace std;
 5 
 6 class MyString:public string
 7 {
 8 public:
 9     MyString(const MyString & s):string(s){};
10     MyString(const string & s):string(s){};
11     MyString(const char * s):string(s){};
12     MyString(){};
13 
14     MyString operator()(int start_index,int length){
15 
16     MyString substr  =  this->substr(start_index,length);
17     return substr;
18 
19 }
20 
21     ~MyString(){};
22 };
23 
24 
25 
26 int CompareString( const void * e1, const void * e2) {
27     MyString * s1 = (MyString * ) e1;
28     MyString * s2 = (MyString * ) e2;
29     if( *s1 < *s2 ) return -1;
30     else if( *s1 == *s2 ) return 0;
31     else if( *s1 > *s2 ) return 1;
32 }
33 
34 int main() {
35     MyString s1("abcd-"),s2,s3("efgh-"),s4(s1);
36     MyString SArray[4] = {"big","me","about","take"};
37     cout << "1. " << s1 << s2 << s3<< s4<< endl;
38     s4 = s3; s3 = s1 + s3;
39     cout << "2. " << s1 << endl;
40     cout << "3. " << s2 << endl;
41     cout << "4. " << s3 << endl;
42     cout << "5. " << s4 << endl;
43     cout << "6. " << s1[2] << endl;
44     s2 = s1; s1 = "ijkl-";
45     s1[2] = 'A' ;
46     cout << "7. " << s2 << endl;
47     cout << "8. " << s1 << endl;
48     s1 += "mnop";
49     cout << "9. " << s1 << endl;
50     s4 = "qrst-" + s2;
51     cout << "10. " << s4 << endl;
52     s1 = s2 + s4 + " uvw " + "xyz";
53     cout << "11. " << s1 << endl;
54     qsort(SArray,4,sizeof(MyString), CompareString);
55     for( int i = 0;i < 4;++i )
56         cout << SArray[i] << endl;
57     //输出s1从下标0开始长度为4的子串
58     cout << s1(0,4) << endl;
59     //输出s1从下标为5开始长度为10的子串
60     cout << s1(5,10) << endl;
61     return 0;
62 }
View Code

  这里,MyString 虽然没说,可是得到了string全部的操做符重载(=,+....)还有全部的函数(substr)。惟一须要好好设计的就是构造函数。

相关文章
相关标签/搜索