1. 程式人生 > 其它 >C++快速入門——基礎知識筆記

C++快速入門——基礎知識筆記

技術標籤:C/C++c++C++快速入門

1、this

this是個特殊指標,在class裡面指向當前物件,例如。

class Person
{
private:
    char    *name;
public:
    void setName(char *name)
    {
        this->name = name;
    }
};

2、::

  1. 用於指定當前函式屬於某個類,例如setAge函式屬於Person類的一個方法。
  2. 用於指定呼叫的函式是來自哪個名稱空間,例如呼叫的是名稱空間A裡面的PrintVersion函式。
void Person::setAge(int age)
{
    this->age = age;
}

A::PrintVersion();

在這裡插入圖片描述

3、 using用法:

  1. using A::Person; 宣告使用名稱空間A裡面的Person類,不宣告的話在使用類之前要加名稱空間。
  2. using A::PrintVersion; 匯入名稱空間A裡面的PrintVersion函式,不宣告的話在呼叫函前面要加名稱空間。
  3. 直接using namespace A; 一次性匯入名稱空間A涉及的類和函式。

4、cout

需要包含標頭檔案iostream:#include ,不需要加.h,引用標準名稱空間std。cout使用方法:cout<<"age = “<<age<<”,name = "<<name<<endl;這裡的<<是過載了左移運算,達到字串拼接的效果,enld是回車換行。

cout有時候的輸出格式不是我們想要的,如下會輸出i = d,需要加強轉來解決。

uint8_t i = 100;
cout<<"i = "<<i<<endl;

5、建構函式

  1. 呼叫無參建構函式的方法:Person person;或者Person person(“zhangsan”,18);而Person person()只是宣告一個函式,並不是定義一個類變數。
  2. 建構函式需要public屬性。
  3. 指標方式定義類變數:Person *per = new Person;或者Person *per = new Person();這兩種方式都是可以的,都會呼叫無參的建構函式。刪除一個類:delete per。
  4. 建構函式傳入預設引數,如Person(int age,char *name = “zhangsan”)。
  5. 一旦定義了有參建構函式,則必須定義一個無參建構函式。

6、解構函式

解構函式使用者釋放一些類裡面動態分配的記憶體,函式定義格式為:類名(),例如Person(),解構函式無參。

7、類的預設函式

  1. 預設建構函式:一個無參的建構函式,函式的內容為空

  2. 預設的解構函式:函式的內容為空

  3. 預設的拷貝函式:是一個特殊的建構函式,其入參是該類的引用。當建立一個類的時候,如果傳入的引數是同一個類的引用,那麼會拷貝一份,注意傳入的引數是類引用,而不是指標。例如:

    Person *per = new Person(25,"Dokin");
    Person *per2 = new Person(*per);
    或
    Person per(25,"Dokin");
    Person per2(per);
    

    類的預設拷貝函式在使用上有風險,因為創建出的類物件,其成員如果是指標型別,會和類引用指向同一空間,在記憶體分配和釋放上就有可能產生被重複釋放的問題,這種情況下需要重寫拷貝函式。

8、建構函式呼叫順序

  1. 按執行中定義物件的順序呼叫建構函式,靜態物件只調用一次建構函式,全域性物件在main函式執行前被構造。

  2. 類定義中如果使用了別的類,那麼會先按編碼順序依次呼叫別的類的建構函式,然後再呼叫本類的建構函式。

  3. 類的建構函式需要構造別的類時,在建構函式後面加:號,多個類用,隔開。如下面例子所示。注意,構造順序和:後面的順序無關,只和定義類成員的順序有關,即下面的例子依然是father先被構造。析構的順序則和構造的順序剛好相反。

    class Student
    {
    private:
        Person father;
        Person mother;
        int age;
    public:
        Student(){}
        Student(int age,char *father,int father_age,char *mother,int mother_age)\
            :mother(mother,mother_age),father(father,father_age)
        {
            this->age = age;
        }
    };
    
    int main(int argc,char **argv)
    {
        Student Dokin(15,"bill",40,"lily",39);
        return 0;
    }
    

9、類的靜態成員和方法

類裡面可以使用static對成員和方法進行修飾,表明該成員或方法屬於類,而不是屬於類的例項物件。

類的靜態成員即使是private許可權,也可以通過類名來直接訪問。

靜態方法只能訪問靜態變數,不能訪問非靜態變數,因為靜態變數屬於類,而非靜態變數屬於類的例項物件。

類的例項物件也可以訪問類的靜態方法。

類的靜態方法可以在類裡面宣告然後類的外面定義,例如:

class Person
{
private:
    static int cnt;
public:
    static int getCnt();
    /* ... */
}

int Person::getCnt()
{
    return Person::cnt;
}

類定義時並沒有分配記憶體空間,因此需要在外部進行定義和初始化,下面是一個例子。

class Person
{
private:
    char    *name;
    int     age;
    static int cnt;

public:
    Person()
    {
        cnt ++;
        this->name = NULL;
    }
    ~Person()
    {
        cnt --;
    }
    static int getCnt()
    {
        return cnt;
    }
}

int Person::cnt = 0;

int main(int argc,char **argv)
{
    Person per1;
    Person per2;
   	
    cout<<"cnt = "<<Person::getCnt()<<endl;
}

10、友元函式

在類的定義中,可以用friend關鍵字來宣告一個友元函式,友元函式可以直接訪問所在類的私有成員,從而提高效率。下面是一個例子。

#include <iostream>
using namespace std;

class Point
{
private:
    int x;
    int y;

public:
    Point(){}
    Point(int x,int y):x(x),y(y){}
    void print()
    {
        cout<<"x = "<<x<<",y = "<<y<<endl;
    }
    friend Point addPoint(Point &p1,Point &p2);
};

Point addPoint(Point &p1,Point &p2)
{
    Point point;

    point.x = p1.x + p2.x;
    point.y = p1.y + p2.y;

    return point;
}

int main(int argc,char **argv)
{
    Point p1(1,2);
    Point p2(3,4);
    Point p3 = addPoint(p1,p2);

    p3.print();
}

11、const成員函式

在成員函式後面加上const表示此函式沒有修改操作,如void printInfo(void)const。

12、運算子過載

例如過載++號運算,那麼函式名為Point operator++(Point p),通過入參的不同可以實現運算子的不同功能,例如以下++的實現。

/* 實現++p */
Point operator++(Point &p)
{
    p.x += 1;
    p.y += 1;
    return p;
}

/* 實現p++ */
Point operator++(Point &p, int a)
{
    Point temp;
    
    temp = p;
    p.x += 1;
    p.y += 1;
    return temp;
}

上述函式通過函式入參的不同實現了函式過載,實現了前++和後++。

注意Point operator++(Point &p)函式中定義了返回了一個臨時變數p,這會造成臨時變數p的建構函式和解構函式被呼叫,從而影響函式執行效率,最佳的實現方式如下,返回一個引用,這樣就不會有臨時變數,也就不會呼叫建構函式和析構函數了。

/* 實現++p */
Point& operator++(Point &p)
{
    p.x += 1;
    p.y += 1;
    return p;
}

過載=號運算子可以解決值拷貝造成的問題:拷貝類的指標成員,導致兩個類的成員指向同一塊地址。過載=號可以在過載函式裡對指標成員進行記憶體申請和銷燬,避免指向同一地址。

以下操作的結果是不同的:p2 = p1會呼叫預設的拷貝函式,而不是呼叫operator=過載函式。先定義p3,然後p3=p1這樣才會呼叫operator=過載函式。

Person p1;
Person p2 = p1;

Person p3;
p3 = p1;