C++學生筆記一覽

C++與 C語言的區別


1. cstring與string的區別。

(<string.h> == <cstring>)

  1. 在C語言中<cstring>主要是為了使用字符串函數 在C++中<string>主要是為了使用std::string類。例如:memcmp;memcpy;memmove;strlen;
  2. 在字符串聲明中的區別例如:char str[20]; (C中必須聲明字符串的長度) 而C++中只需要 string str;且使用一個null字符作為結尾; (C++的string類型不需要使用null)
  3. 在字符串的操作方式上有所不同例如:strcpy(name,”peter”); name = “pepter”; str5 = str2 + str3; str2<str3;
  4. C++的string類型不能用printf內的%s列印出來 string類中提供了c_str();通過.的方式去訪問類中的c_str(),即會返回當前字符串的首地址 (char *),就可以通過%s來列印string類型的字符串了。

2.結構體的區別

struct和class可以設定訪問權限,class默認權限為私有、struct默認權限為公有;

在C++中結構體就是類:(多個事物的個體的共同屬性);

屬性:(數據類型描述)+(成員函數);

對象: 類的具體化/實例化;**

!!!當函數實現寫在結構體內部時,會變為inline(內聯函數),為了使程序運行更快,但會占用更多記憶體,所以如果函數比較長建議類內聲明,類外實現;

函數類外實現需要加作用域表示是哪個類的函數,例如:void 類名::函數名(參數列表){};

2.1構造函數,析構函數

2.1.1構造函數

分為構造函數拷貝構造函數

class man{
public:
//構造函數
man(string name = "0",int age = 0){      //當沒有參數或參數不夠時,使用默認值
this->name = name;                   //用來區別形參和數據成員同名的問題,this表示每一個對象的首地址。
this->age = age;
}
//拷貝構造函數
man(const man &p){                      //拷貝構造函數參數用const修飾,防止改動原件
name = p.name;
age = p.age;
}
private:
string name;
int age;
};

只要創建新的對象,就會調用一次構造函數或拷貝構造函數;

默認的拷貝構造函數也可以用delete刪除;

2.1.2析構函數

對象執行結束時被調用,釋放記憶體;

如果對象創建在堆區需要手動釋放(delete)才會自動調用析構函數,析構函數也需要手寫delete;

穿褲子的析構順序;

靜態變量是最後被析構的;(因為靜態變量最先被構造)

delete可以直接調用析構函數;

class man{
public:
//構造函數
man(char* name = '0',int age = 0){
this->name = new char(strlen(name)+1);
strcpy(this->name,name);
this->age = age;
}
//析構函數
~man(){
delete[] name;
name = nullptr;
}
private:
char* name;
int age;
};

2.1.2.1深拷貝與淺拷貝

  1. 淺拷貝是指初始化對象時在棧區
  2. 深拷貝是指初始化對象時有成員被創建在堆區 當構造函數初始化數據,數據存放在堆區時,成員初始化完成調用析構函數時,堆區的記憶體被重複釋放。此時需要通過深拷貝來解決問題。class
    man{
    public:
    //構造函數
    man(char* name = ‘0’,int age = 0){
    this->name = new char(strlen(name)+1);
    strcpy(this->name,name);
    this->age = age;
    }
    //深拷貝構造函數
    man(const man &p){ //拷貝構造函數參數用const修飾,防止改動原件;
    name = new char(*p.name); //name = new char[strlen(p.name)+1];strcpy(name,p.name);

    age = p.age; //new() 分配這種類型的一個大小的記憶體空間,並以括號中的值來初始化這個變量;
    } //new[]
    分配這種類型的n個大小的記憶體空間,並用默認構造函數來初始化這些變量;
    //析構函數
    ~man(){
    delete[] name;
    name = nullptr;
    }
    private:
    char* name;
    int age;
    };

2.2初始化對象

2.2.1構造函數初始化

構造函數沒有返回值類型;

函數名和類名相同;

可以函數重載;

如果沒有創建構造函數,會自動創建一個構造函數;

可以通過 類名 = delete; 的方式刪除默認的構造函數;

不需要自己調用,只要創建對象就會調用相應的構造函數;

一般情況默認的構造函數是公有類型;

struct Girl {
string name;
int age;
Girl(string sName, int sAge)  {
name = sName;
age = sAge;
}
};
Girl MM_1("墨菲特", 18);
struct Girl {
string name;
int age;
//初始化參數列表寫法
Girl(string sName, int sAge) :name(name),age(age) {}
};

2.2.2引用初始化

struct Girl {
string name;
int age;
string& getname(){
return name;
}
int& getage(){
return age;
}
};
Girl MM_1;
MM_1.getname() = "墨菲特";
MM_1.getage() = 18;

3.特殊成員

3.1const成員

  1. const 數據成員只能採用初始化參數列表的方式進行初始化構造函數必須要初始化常數據成員
class peple{
public:
peple() :age(0){}
private:
const int age;
};
  1. const 成員函數const放在函數 )後面;函數內是不能對數據成員修改的,只能讀;常成員函數可以和普通函數共存
void print_age(){}              //常成員函數可以和普通函數共存
void print_age() const
{
//函數內是不能對數據成員修改的,只能讀
cout<< age <<endl;
}
  1. const 對象常對象只能調用常成員函數普通對象優先調用普通函數
const peple  man("墨菲特");    //只能調用常成員函數

3.2static成員

  1. static數據成員相當於寫在類中的全局變量;聲明需要前綴,並且必須在類外進行初始化,類外初始化不需要static前綴;依舊受權限限定詞限定;使用可以不需要對象,靜態數據成員屬於類,不屬於變量;
  2. static成員函數聲明需要前綴,並且必須在類外進行初始化,類外初始化不需要static前綴;訪問靜態數據成員,調用不需要對象;訪問非靜態數據成員,需要指定對象(函數參數需要對象);靜態函數的調用不需要對象;
class peple{
public:
static void print_age();
private
static int age;
}
peple::age = 18;
void peple::print_age(){
cout<<age<<endl;
};

4.友元

  1. 友元函數在函數前使用friend修飾;在類中聲明,在類外實現不需要作用域以及friend修飾詞;在當前函數中賦予對象具有打破類的權限限定
class MM {
friend void makeBoyFriend();
public:
MM(string name, int age, int money) :name(name), age(age), money(money) {}
private:
string name;
int age;
int money;
};
void makeBoyFriend() {
MM boy("yykk", 18, 100);
cout << boy.name << ":" << boy.age << boy.money << endl;
}
  1. 友元類在當前類的任何地方girl對象都可以訪問girl任何屬性
class A{
friend class b;
};

5.類的組合

將一個其他類作為自身類的成員;

  1. 組合出來的類必須以初始化參數列表方式調用被組合類的構造函數
class Cloths {
public:
////通過預設的方式寫,下面組合類(MM)就不需要用初始化參數列表寫被組合類的構造函數了
Cloths(int color = 0) :color(color) {}
protected:
int color;
};
class Cosmetics {
public:
Cosmetics(int moeny = 0) :money(money) {}
protected:
int money;
};
class MM {
public:
//組合出來的類必須以初始化參數列表方式調用被組合類的構造函數
MM(string name, int color, int money) :Cosmetic1(money), Cloth1(color) {
this->name = name;
}
protected:
string name;
//構造被組合的類的構造函數順序和這個聲明順序有關
Cloths Cloth1;
Cosmetics Cosmetic1;
};

來源:kknewsC++學生筆記一覽