您的浏览器不支持CSS3,建议使用Firfox、Chrome等浏览器,以取得最佳显示效果

C++ 快速复习

编程 514℃ 0 2年前 (2015-09-03)

 

未命名.html

C++ 快速复习

无论如何,学习语言最为重要的,请记得多翻参考手册:
中文版点击这里
英文版点击这里

 

 

string 类

构造函数

explicit string ( ); 
/*默认构造函数,初始化string为一个空串*/
Content is initialized to an empty string. 

string ( const string& str );
/*复制构造函数,复制一个string对象*/
Content is initialized to a copy of the string object str. 

/*使用string对象str从pos到npos的字符来初始化*/
string ( const string& str, size_t pos, size_t n = npos ); 
Content is initialized to a copy of a substring of str. The substring is the 
portion of str that begins at the character position pos and takes up to n characters (it takes less than n if the end of str is reached before). 

/*使用c字符串s的开头到第n个字符来初始化*/
string ( const char * s, size_t n ); 
Content is initialized to a copy of the string formed by the first n characters in the array of characters pointed by s. 

/*使用c字符串s来构造string*/
string ( const char * s ); 
Content is initialized to a copy of the string formed by the null-terminated character sequence (C string) pointed by s. The length of the caracter sequence is determined by the first occurrence of a null character (as determined by traits.length(s)). This version can be used to initialize a string object using a string literal constant. 

/*使用n个字符c来构造*/
string ( size_t n, char c ); 
Content is initialized as a string formed by a repetition of character c, n times. 

template<class InputIterator> string (InputIterator begin, InputIterator end); 
If InputIterator is an integral type, behaves as the sixth constructor version (the one right above this) by typecasting begin and end to call it:

string(static_cast<size_t>(begin),static_cast<char>(end)); 
In any other case, the parameters are taken as iterators, and the content is initialized with the values of the elements that go from element referred by iterator begin to the element right before the one referred by iterator end.

强制类型转化

关于强制类型转换,必须知道:

  • 在类层面中,上行转换,也就是子类沿着继承树向上转换为父类是安全的,因为C++的多态性决定了使用父类指针来引用子类是安全的。
  • 在类层面中,下行转换,也就是父类沿着继承书向下转换为子类是不安全的。

以上两条规则,从面向对象层面来说,就是符合子类定义的对象一定是父类,而符合父类定义的对象则不一定是子类对象。例如:鲫鱼是鱼表述正确,但鱼是鲫鱼则表述错误。

static_cast

不带运行时类型检查,也就是说使用这种强制类型转化与C的传统类型转化是一致的。编译器没有义务来保证转换的安全性。无论是上行还是下行转换,编译器都不会报错。

dynamic_cast

运行时类型检查的强制类型转换,也就是说使用这种强制类型转化,会检测从源类型到目标类型是否合法,如果不合法则报错。比如

  • 下行转换会报错
  • 如果type-id是类指针类型,那么exdivssion也必须是一个指针,如果type-id是一个引用,那么exdivssion也必须是一个引用。否则报错。

const_cast

用法:const_cast (exdivssion)
该运算符用来修改类型的const或volatile属性。除了const 或volatile修饰之外, type_id和exdivssion的类型是一样的。

  • 常量指针被转化成非常量指针,并且仍然指向原来的对象;
  • 常量引用被转换成非常量引用,并且仍然指向原来的对象;
  • 常量对象被转换成非常量对象。

reindivter_cast

用法:reindivter_cast (exdivssion)
type-id必须是一个指针、引用、算术类型、函数指针或者成员指针。
它可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针(先把一个指针转换成一个整数,
在把该整数转换成原类型的指针,还可以得到原先的指针值)。

该运算符的用法比较多。

友元

  • 一个类的友员必须是一个类或者一个函数
  • 重载函数不是同一个函数,所以将函数F(int)设置为友员后,它的其它重载函数都不能成为友元。

复制控制

复制构造函数

当一个构造函数的参数列表只有一个形参,并且该形参是一个对该类型的引用且为const。比如

class Demo{
    public:
        Demo(const Demo &){....}
}

大多数类应当定义默认构造函数和复制构造函数,否则类的使用受许多限制。

析构函数

  • 当类生命周期结束时,析构函数被调用。比如
    • 局部类在函数运行结束时
    • 类被delete时
  • 类的默认合成析构函数会逐个释放对象的非static成员
  • 如果类分配资源,那么就需要编写析构函数而不是使用默认析构函数,比如
    class Demo{
    public:
      Demo():p(new Demo1){}
    private:
      class Demo1 *p;
    }
    

    这个类应当写一个析构函数,因为它分配了资源

      Demo():p(new Demo1){}
    

    默认析构函数只会释放p的空间,而不会释放p指向的Demo1的空间。

  • 对象的构造顺序是从父类开始构造,无论如何,编译器会现让父类构造对象先被调用,然后再调用子类对象。
  • 显示调用父类构造函数只能在初始化列表内进行,而不能在子类的构造函数体内调用。例如

    7 class Base{
    8     public :
    9         Base(){ cout << "基类默认构造函数" << endl;}
    10         Base(int d):data(d) { cout << "基类显式构造函数 d = " << d << endl; }
    11     private:
    12         int data;
    13 };
    14 
    15 class Child: public Base{
    16     public:
    17         Child(){cout << "子类默认构造函数" << endl;}
    18         Child(int data):Base(data){ cout << "子类显式构造函数"<<endl;}
    19         Child(int a, int b) { cout << "子类显示构造函数1 a = "
    20                                 << a << "b = " << b << endl;Base(b); }
    21 };
    22 
    23 int main(void)
    24 {
    25     Child *pH = new Child;
    26     Child *PH1 = new Child(int(15));
    27     Child *pH2 = new Child(int(13),int(24));//!!错误
    28     if (!(pH && PH1))
    29         return 0;
    30     return 1;
    31 }
    

    在这里,子类的构造函数中显示构造函数1是错误的,因为此时在函数题内显式调用了父类的构造函数,这是不行的。在子类构造阶段,this指针没有拿到,在构造函数中的Base会被当作局部变量来处理,当构造函数退出的时候,局部变量会被销毁。

  • 析构先从子类开始,无论如何编译器会让子类的析构函数先被调用,然后再调用父类构造函数,子类无需显式调用父类析构函数。

    class Child : public Parent{....};  
    
    int main(void)
    {  
      Child *pCH = new Child;
      delete pCH;
    }
    

    这里会先调用Child的析构函数再去在Child的析构函数中调用Parent的析构函数,这个是隐式调用的。而如果delete操作的对象是一个指向Child的Parent指针,就会直接调用Parent的析构函数了事,而子类得不到析构。这时候需要:

  • 将父类的析构函数声明为虚函数。于是调用关系就是这样:当delete pParent的时候,直接调用父类的析构函数,此时由于多态性,就会调用到子类的析构函数,而子类的析构函数中有编译器隐式添加的对父类析构函数的调用代码,如此一来,子类和父类都能得到析构。例:

    /*
    *  以下代码输出为:
    *   DisConstructor of Child
    *   DisConstructor of Parent
    *   DisConstructor of Parent
    */   
    
    1 #include <iostream>  
    2 
    3 using std::cout;  
    4 using std::cin;  
    5 using std::endl;  
    6   
    7 class Parent{  
    8 public:  
    9     ~Parent(){cout << "DisConstructor of Parent" << endl;}    
    10 };  
    11   
    12 class Child : public Parent{   
    13 public :    
    14     ~Child(){cout << "DisConstructor of Child" << endl;}     
    15 };   
    16    
    17 int main(void)   
    18 {   
    19     Child *pCH = new Child;   
    20     Parent* pP = new Child;   
    21       
    22     delete pCH;   
    23     delete pP;   
    24 }    
    
    /*
    *  以下代码输出为:
    *   DisConstructor of Child
    *   DisConstructor of Parent
    *   DisConstructor of Child
    *   DisConstructor of Parent
    */
    1 #include <iostream>
    2 
    3 using std::cout;
    4 using std::cin;
    5 using std::endl;
    6 
    7 class Parent{
    8 public:
    9     virtual ~Parent(){cout << "DisConstructor of Parent" << endl;}
    10 };
    11 
    12 class Child : public Parent{
    13 public :
    14     ~Child(){cout << "DisConstructor of Child" << endl;}
    15 };
    16 
    17 int main(void)
    18 {
    19     Child *pCH = new Child;
    20     Parent* pP = new Child;
    21 
    22     delete pCH;
    23     delete pP;
    24 }
    
0

暂无评论

评论前:需填写以下信息,或 登录

ERROR: si-captcha.php plugin: GD image support not detected in PHP!

Contact your web host and ask them to enable GD image support for PHP.

ERROR: si-captcha.php plugin: imagepng function not detected in PHP!

Contact your web host and ask them to enable imagepng for PHP.

用户登录

忘记密码?