C++(14)--面向對象

面向對象

  • 1.面向對象編程(難點)
  • 2.類和對象
    • demo1:地主類的實現版本1
    • demo2:地主類的實現版本2
  • 3.訪問修飾符
    • demo3:外部修改成員變量不安全(版本3)
    • demo4: 使用封裝防止直接修改成員變量(版本3)
    • demo5:進一步封裝:設置/獲取名字,修改積分(版本4)
  • 4.構造函數與析構函數(重點)
    • 4.1默認構造函數
      • demo6: 使用構造函數進行成員變量的初始化
    • 4.2 帶參構造函數
      • demo7:學生類構建--堆內存對象/棧內存對象
    • 4.3 析構函數
      • demo8:學生類析構函數演示
  • 5.this指針(重點)
    • demo9:學霸返回引用的使用

《老九學堂C++課程》《C++ primer》學習筆記。《老九學堂C++課程》詳情請到B站搜索《老九零基礎學編程C++入門》
-------------簡單的事情重復做,重復的事情用心做,用心的事情堅持做(老九君)---------------

1.面向對象編程(難點)

oop: object oriented programming

何為面向對象:基于對象的概念,以對象為中心,以類和繼承為構造機制,來認識、理解、刻畫客觀世界;涉及構建相應的軟件系統(模擬現實)

1.對象–有數據和容許的操作組成的封裝體,與客觀實體有直接的對應關系(屬性和方法的集合)

面向對象不是某一種語言的特性,而是一種編程思想。原來面向過程代碼超過10W行就會難管理,原來有因為飛機控制程序中一個,寫成.號造成的空難。

舉個粒子:斗地主游戲的開發
面向過程:一步一步來,很多很多的過程函數:開始游戲-洗牌-發牌-顯示手牌…-輸出結果

面向對象:
1.游戲參與者,行為模式是相同的–玩家對象,相同的屬性和行為;
2.進行游戲的場景–牌桌對象,負責現實游戲的界面及內容;
3.游戲規則系統–裁判對象,負責判定牌面、輸贏;

小結:
1.面向過程編程,首先考慮要遵循的步驟,然后考慮如何表示這些數據
2.oop編程,首先會考慮數據,包括數據的表示和數據的使用

2.類和對象

面向對象的編程流程:
1.抽象:從具體食物抽取共同的本質特征,【處理復雜問題的技巧–簡化、抽象】

地主對象:外表特征–胖,留兩撇胡子,兩顆大金牙;行為特點–先出牌,多摸三張牌

2.用類封裝:將抽象轉換為用戶定義類型的工具,將數據表示和操作數據的方法組合成一個整體。類的實例成為對象(對象的集合就是類,還可以這么理解:類就是對象模版),類中的變量和函數稱為成員。

地主類:
成員變量:名稱、積分、手牌
成員函數:摸牌、出牌、產看積分

類的聲明:使用class/struct 關鍵字聲明,
兩者的區別:使用class聲明的類默認成員是私有的(private),struct聲明的類默認成員是共有的(public)。
推薦使用class聲明類;struct聲明結構,只包含數據POD,老式數據

class 類名{};
struct 類名{};

頭文件中聲明類(.h/.cpp),專門有一個類名.cpp文件實現類。

demo1:地主類的實現版本1

–LandOwnerV1.cpp 文件中既聲明又實現,包含main 函數的main.cpp文件中調用

// mian.cpp 文件
#include "LandOwnerV1.cpp"
int main(){// 類,對象實驗LandOwnerV1 landOwner1; // 聲明了一個LandOwner1類型的變量landowner1// 調用對象的成員方法, 不能直接使用對象的私有成員// landOwner1.cards[0] = 0; 'cards' is a private member of 'LandOwnerV1' ,直接報錯landOwner1.TouchCard(100);return 0;
}
// LandOwnerV1.cpp 文件既聲明又實現
#include <iostream>
using namespace std;
// .hpp 一般包含實現的內聯函數,通常用于模版類這種聲明與實現共存的情況
// 建議:只要不是純模版,一律使用.h 作為頭文件后綴, .cpp 作為函數的實現文件
// 地主類的聲明、實現
class LandOwnerV1 {private:string name;	// 名稱long score;		// 積分int cards[20];	// 手牌數組public :LandOwnerV1() {};	// 默認構造函數~LandOwnerV1() {};	// 默認析構函數void TouchCard(int CardCount){// 暫時省略函數實現cout << name << "摸了" << CardCount << "張牌" << endl;}void ShowScore(){cout << name << "當前的積分為:" << score << endl;}};

輸出

摸了100張牌

demo2:地主類的實現版本2

–LandOwnerV2.h中聲明,LandOwnerV2.cpp中實現,main.cpp文件中調用

成員函數沒有調用成功

// mian.cpp 文件
#include "LandOwnerV2.h"  // 關注.h 文件
using namespace std;
int main(){LandOwnerV2 landowner2;landowner2.name = "小明";//landowner2.TouchCard(20);  // 這個方法實現不了cout << landowner2.name << endl;return 0;
}
// LandOwnerV2.h
#include <iostream>
using namespace std;
// .hpp 一般包含實現的內聯函數,通常用于模版類這種聲明與實現共存的情況
// 建議:只要不是純模版,一律使用.h 作為頭文件后綴, .cpp 作為函數的實現文件
// 地主類的聲明class LandOwnerV2 {private:long score;		// 積分int cards[20];	// 手牌數組public :string name;	// 名稱LandOwnerV2();	// 構造函數聲明~LandOwnerV2();	// 析構函數聲明 void TouchCard(int);		// 聲明摸牌函數void PlayCard(int);		    // 聲明出牌函數void ShowScore();			// 聲明產看積分函數
};
// LandOwnerV2.cpp
#include <iostream>
#include "LandOwnerV2.h"
using namespace std;LandOwnerV2::LandOwnerV2()
{//ctor
}void LandOwnerV2::TouchCard(int CardCount){cout << name << "摸了" << CardCount << "張牌" << endl;
}
void LandOwnerV2::ShowScore(){cout << name << "當前的積分為:" << score << endl;
}LandOwnerV2::~LandOwnerV2()
{//dtor
}

(xcode 太不友好了,寫到類分文件時就無法編譯,棄坑!轉向CLION,友好很多。)

3.訪問修飾符

public: 修飾的成員在任意地方都可以訪問
private:修飾的成員只能在類中或者友元函數中訪問, 私有屬性可以習慣性在名字前面加一個_
protected:修飾的成員可以在類中函數、子類函數、友元函數中訪問

(數據隱藏:不希望別人隨意操作,對應的操作叫做封裝)

在修飾關鍵字放在類定義的關鍵字中,加冒號,無修飾關鍵字默認為private

class 類名{
修飾符:成員類標;
};

demo3:外部修改成員變量不安全(版本3)

非私有成員,會被直接修改–修改地主積分

// mian.cpp 文件
#include <iostream>
#include "LandOwnerv3.h"
using namespace std;
int main(){// 訪問修飾符的實驗LandOwnerv3 landOwner3;landOwner3.name = "巴依老爺";// 修改地主積分landOwner3.score = 100;landOwner3.ShowScore(landOwner3.score);return 0;
}
// LandOwnerv3.h 文件
// Created by 陳瑩瑩 on 2021/1/28.
#include <iostream>
#ifndef HELLOWORLD_LANDOWNERV3_H
#define HELLOWORLD_LANDOWNERV3_H
using namespace std;
class LandOwnerv3 {int cards[20];	// 手牌數組
public :string name;long score;		// 積分LandOwnerv3();	// 構造函數聲明, 沒有返回值~LandOwnerv3();	// 析構函數聲明void TouchCard(int);		// 聲明摸牌函數void PlayCard(int);		    // 聲明出牌函數void ShowScore(int);			// 聲明產看積分函數
};
#endif //HELLOWORLD_LANDOWNERV3_H
// LandOwnerv3.cpp 文件
// Created by 陳瑩瑩 on 2021/1/28.
// 用來演示封裝的基本概念
#include <iostream>
#include "LandOwnerv3.h"
using namespace std;
LandOwnerv3::LandOwnerv3()
{//ctor
}
void LandOwnerv3::ShowScore(int score){cout << name     << "當前的積分為:" << score << endl;
}LandOwnerv3::~LandOwnerv3()
{//dtor
}

輸出:

巴依老爺當前的積分為:100

demo4: 使用封裝防止直接修改成員變量(版本3)

但是如此操作使得大家可以隨意修改這個積分,有一些不合理的積分就會出現。為了解決積分被賦值為不合理的情況,需要將成員變量score進行封裝(使用方法來實現對成員的封裝)
demo4:類封裝概念,get/set方法

// mian.cpp 文件
#include <iostream>
#include "LandOwnerv3.h"
using namespace std;
int main(){// 訪問修飾符的實驗LandOwnerv3 landOwner3;landOwner3.name = "巴依老爺";// 修改地主積分landOwner3.SetScore(-100);landOwner3.ShowScore();return 0;
}
// LandOwnerv3.h 文件
// Created by 陳瑩瑩 on 2021/1/28.
#include <iostream>
#ifndef HELLOWORLD_LANDOWNERV3_H
#define HELLOWORLD_LANDOWNERV3_H
using namespace std;
class LandOwnerv3 {long score;		// 積分int cards[20];	// 手牌數組
public :string name;LandOwnerv3();	// 構造函數聲明, 沒有返回值~LandOwnerv3();	// 析構函數聲明void TouchCard(int);		// 聲明摸牌函數void PlayCard(int);		    // 聲明出牌函數void ShowScore();			// 聲明產看積分函數// 定義成內聯函數即可void SetScore(long lScore){// 通過條件判斷封裝了score的賦值過程if(lScore < 0){score = 0;}else{score = lScore;}}
};
#endif //HELLOWORLD_LANDOWNERV3_H
// LandOwnerv3.cpp 文件
// Created by 陳瑩瑩 on 2021/1/28.
// 用來演示封裝的基本概念
#include <iostream>
#include "LandOwnerv3.h"
using namespace std;
LandOwnerv3::LandOwnerv3()
{//ctor
}
void LandOwnerv3::ShowScore(){cout << name     << "當前的積分為:" << score << endl;
}LandOwnerv3::~LandOwnerv3()
{//dtor
}

輸出:

巴依老爺當前的積分為:0

demo5:進一步封裝:設置/獲取名字,修改積分(版本4)

// mian.cpp 文件
#include <iostream>
#include "LandOwnerv41.h"
using namespace std;
int main(){// 訪問修飾符的實驗LandOwnerv41 landOwner4;landOwner4.SetName("巴依老爺");cout << landOwner4.GetName() << endl;// 修改地主積分landOwner4.SetScore(-100);landOwner4.ShowScore();return 0;
}
// LandOwnerv41.h 文件
// Created by 陳瑩瑩 on 2021/1/29.
#ifndef HELLOWORLD_LANDOWNERV41_H
#define HELLOWORLD_LANDOWNERV41_H#include <iostream>
using namespace std;
class LandOwnerv41 {long score;		// 積分int cards[20];	// 手牌數組string name;
public :LandOwnerv41();	// 構造函數聲明, 沒有返回值~LandOwnerv41();	// 析構函數聲明void TouchCard(int);		// 聲明摸牌函數void PlayCard(int);		    // 聲明出牌函數void ShowScore();			// 聲明產看積分函數// 定義成內聯函數即可void SetScore(long lScore){// 通過條件判斷封裝了score的賦值過程if(lScore < 0){score = 0;}else{score = lScore;}}string GetName(){return name;}void SetName(string lName){name = lName;}};
#endif //HELLOWORLD_LANDOWNERV41_H
// LandOwnerv41.cpp 文件
// Created by 陳瑩瑩 on 2021/1/29.
#include "LandOwnerv41.h"
#include <iostream>
using namespace std;
LandOwnerv41::LandOwnerv41()
{//ctor
}
void LandOwnerv41::ShowScore(){cout << name     << "當前的積分為:" << score << endl;
}LandOwnerv41::~LandOwnerv41()
{//dtor
}

4.構造函數與析構函數(重點)

構造函數:與類同名,沒有返回值
構造函數的作用:給編譯器看的,編譯器在對象被創建時,為對象分配內存空間,并自動調用構造函數以完成成員的初始化
構造函數的種類:無參數構造,一般構造(重載構造),拷貝構造。(本節主要介紹:無參構造,一般構造)

4.1默認構造函數

demo6: 使用構造函數進行成員變量的初始化

// mian.cpp 文件
//演示構造函數
#include "LandOwnerv41.h"
using namespace std;
int main(){LandOwnerv41 landOwnerv4;   // 省略了默認構造LandOwnerv41 landOwnerv4();   // 標準寫法,但是不調用默認構造函數了?--不輸出內容了return 0;
}
// LandOwnerv41.h 文件
// 與demo5一致
// LandOwnerv41.cpp 文件
// Created by 陳瑩瑩 on 2021/1/29.
//
#include "LandOwnerv41.h"
#include <iostream>
#include <memory.h>
using namespace std;
LandOwnerv41::LandOwnerv41()
{cout << "LandOwnerV41的無參數構造函數(默認構造)被調用!" << endl;name = "默認地主";score = 0;//將用戶的手牌數組初始化為0memset(cards, 0, sizeof(cards)/sizeof(cards[0]));cout << "初始化的結果如下:" << endl;cout << "名字:" << name << endl;cout << "積分:" << score << endl;cout << "手牌數組:" ;for(int i=0; i < sizeof(cards)/sizeof(cards[0]); i++){cout << cards[i] << "\t";}cout << endl;
}
void LandOwnerv41::ShowScore(){cout << name     << "當前的積分為:" << score << endl;
}LandOwnerv41::~LandOwnerv41()
{//dtor
}

為啥手牌數組的初始化不是全為0?

LandOwnerV41的無參數構造函數(默認構造)被調用!
初始化的結果如下:
名字:默認地主
積分:0
手牌數組:0	0	0	0	0	0	0	0	-375207560	32766	-375207584	32766	0	1	0	0	0	0	0	0	

默認構造顯式寫法:

LandOwnerV4() = default;

注意:
1.如果創建的類中未書寫任何構造函數,系統會自動生成默認的無參構造函數(函數為空,什么都不做)
2.如果書寫了構造函數,系統不會自動生成默認構造函數,如果希望有一個這樣的無參數構造函數,需要自己顯示書寫LandOwnerV4() = default;

4.2 帶參構造函數

語法:

類名::構造(類型1 參數1, 類型2 參數2, ....){// 相關初始化方法
}

demo7:學生類構建–堆內存對象/棧內存對象

1.棧內存中的對象(類似于函數聲明),
具體對象由系統創建并釋放,不用擔心內存泄露。
聲明周期只在聲明區域的大括號內。
棧內存的優勢存取速度快(僅次于寄存器),缺點棧內存中的數據大小生存期是確定的,缺乏靈活性。

自定義類型名 對象名;
Student stu();
Student stu;

2.堆內存中的對象(需要new關鍵字)
p_stu1是指針,必須使用delete釋放
使用靈活可以賦給全局變量,可以把對象作為函數的返回值
用好了

Student *p_stu1= new Student();
Student *p_stu2= new Student();
auto *p_stu3= new Student(); // auto 自動類型判斷,不推薦使用,sizeof 會報錯

類對象推薦放在堆內存中,即使用new來創建對象。

// mian.cpp 文件
#include <iostream>
#include "Student.h"
using namespace std;
int main(){// 演示構造函數,實質就是函數重載Student stu1;Student stu2("馬化騰","普通家庭");     // 在棧內存中直接分配空間,速度塊// 如果構造函數中只有一個參數,且單參數構造函數只有一個,可以直接使用賦值操作進行初始化// Student stu4 = 45stu2.showInfo();// 學生指針類型, 使用new 分配內存空間Student * stu5 = new Student("杰克馬", "毀創阿里");  // 在堆內存中分配空間// 類指針訪問方法要使用 ->stu5 ->showInfo();return 0;
}

輸出結果:

默認構造函數
設置帶參構造
普通家庭馬化騰
設置帶參構造
毀創阿里杰克馬
// Student.h 文件
//
// Created by 陳瑩瑩 on 2021/2/2.
//
#ifndef HELLOWORLD_STUDENT_H
#define HELLOWORLD_STUDENT_H
#include <iostream>
using namespace std;class Student {
private:string m_name;string m_desc;int m_age;
public:Student();          // 默認構造函數Student(string, string);~Student();void showInfo();};
#endif //HELLOWORLD_STUDENT_H
// Student.cpp 文件
//
// Created by 陳瑩瑩 on 2021/2/2.
//
#include <iostream>
#include "Student.h"
using namespace std;Student::Student() {cout << "默認構造函數" << endl;
}
//Student::Student(string name, string desc){
//    // 參數列表不同,函數重載
//    m_name = name;
//    m_desc = desc;
//    cout << "設置帶參構造" << endl;
//}
//初始化參數列表的寫法,和上上面的帶參數構造方法完全相同
Student::Student(string name, string desc):m_name(name), m_desc(desc){cout << "設置帶參構造" << endl;
};void Student::showInfo() {cout << m_desc << m_name << endl;
}
Student::~Student() {}

4.3 析構函數

對象銷毀時自動調用的特殊成員函數, 析構函數一般用來完成清理工作。
析構函數名稱在類名前加一個~,析構函數沒有參數,只能有一個

在棧內存中構造的對象,在棧區(mian函數)銷毀時,類對象會被自動銷毀。在堆內存中構建的類對象,需要手動釋放。

在析構函數內部需要釋放(delete)掉在構造函數中手動分配(new)的空間(對象內部的成員變量)。

1.析構函數用來釋放對象使用的資源,并銷毀對象的非static數據成員.
2.無論何時一個對象被銷毀,都會自動調用析構函數(隱式析構)

demo8:學生類析構函數演示

類對象推薦放在堆內存中,即使用new來創建對象。

// mian.cpp 文件
#include <iostream>
#include "Student.h"
using namespace std;
int main(){// 演示構造函數,實質就是函數重載Student stu1;Student stu2("馬化騰","普通家庭");     // 在棧內存中直接分配空間,速度塊// 如果構造函數中只有一個參數,且單參數構造函數只有一個,可以直接使用賦值操作進行初始化// Student stu4 = 45stu2.showInfo();// 學生指針類型, 使用new 分配內存空間Student * stu5 = new Student("杰克馬", "毀創阿里");  // 在堆內存中分配空間// 類指針訪問方法要使用 ->stu5 ->showInfo();return 0;
}

輸出結果:

默認構造函數
設置帶參構造
普通家庭馬化騰
設置帶參構造
毀創阿里杰克馬
杰克馬被釋放     # 杰克馬為啥被釋放了?
馬化騰被釋放
被釋放
// Student.h 文件
// 與demo7一樣
// Student.cpp 文件
//
// Created by 陳瑩瑩 on 2021/2/2.
//
#include <iostream>
#include "Student.h"
using namespace std;Student::Student() {cout << "默認構造函數" << endl;
}
//Student::Student(string name, string desc){
//    // 參數列表不同,函數重載
//    m_name = name;
//    m_desc = desc;
//    cout << "設置帶參構造" << endl;
//}
//初始化參數列表的寫法,和上上面的帶參數構造方法完全相同
Student::Student(string name, string desc):m_name(name), m_desc(desc){cout << "設置帶參構造" << endl;
};void Student::showInfo() {cout << m_desc << m_name << endl;
}
Student::~Student() {cout << m_name << "被釋放" << endl;
}

5.this指針(重點)

(類似于于python中的self,在python中顯式傳遞self參數)
每個成員函數(包括構造函數和析構函數)都有一個this指針。this指針指向調用對象,可以通過this關鍵字訪問當前對象的成員。

  1. 訪問成員變量:this -> 成員名;
  2. 訪問成員函數:this -> 函數名();

this 在成員函數執行前就已經創建,在析構函數之后被銷毀。

->this 指針的類型為*const,為右值;(可以賦值)
->this指針本身不占用大小,并不是對象的一部分,用sizeof 測不出來大小
->this指針作用域在成員函數內部;
->this指針是類成員函數的第一個默認隱含參數,編譯器自動維護傳遞,編寫者不能顯式傳遞。
->在類非靜態成員函數中才可以使用this指針,其他任何函數都不可以(static是先于類實例存在的,this還沒有創建)

this 返回當前對象的引用,太難用了-- Student & GetSuperScholars(Student &);

demo9:學霸返回引用的使用

//mian.cpp
#include <iostream>
#include "Student.h"
using namespace std;
int main(){Student *ptr_stu1 = new Student("迪麗熱巴","微胖女孩");ptr_stu1->AddScore(78.9);ptr_stu1->AddScore(77.9);ptr_stu1->AddScore(72.9);ptr_stu1->AddScore(79.9);ptr_stu1->AddScore(800);ptr_stu1->showInfo();Student stu2("劉強東","不愛美人");stu2.AddScore(78.9);stu2.AddScore(77.9);stu2.AddScore(72.9);stu2.AddScore(79.9);stu2.AddScore(90);stu2.showInfo();//    Student scholar1 = stu2.GetSuperScholars(*ptr_stu1); 返回new出來的結果,接受的確實棧類型,矛盾,空間釋放的時候會出問題
//    Student scholar2 = ptr_stu1->GetSuperScholars(stu2);Student &scholar1 = stu2.GetSuperScholars(*ptr_stu1);  //返回迪麗熱巴的引用,Student &scholar2 = ptr_stu1->GetSuperScholars(stu2);  //返回迪麗熱巴的引用cout << "學霸是" << scholar1.GetName() << "\t" << scholar2.GetName() << endl;delete ptr_stu1;return 0;//scholar1 棧內存中定義的,main 結束后會自動釋放//scholar2 棧內存中定義的,main 結束后會自動釋放
}
//Student.h
//
// Created by 陳瑩瑩 on 2021/2/2.
//
#ifndef HELLOWORLD_STUDENT_H
#define HELLOWORLD_STUDENT_H
#include <iostream>
using namespace std;class Student {
private:string m_name;string m_desc;int m_age;float *scores; // 學生的分數數組,在某次構造的時候進行初始化int scoreCount; // 學生成績的個數public:Student();          // 默認構造函數Student(string, string);~Student();void showInfo();void InitScores(); // 初始化學生的成績數組,默認分配一個元素空間void AddScore(float score);// 返回值是引用時,是非常危險的。this可以直接修改屬性,建議在函數聲明處加一個const,限制在該函數內部不能通過this指針修改屬性,太麻煩了,要該的地方太多了Student & GetSuperScholars(Student &); //返回學霸對象// 參數處加const 保證不對該參數進行修改。float GetTotal();string GetName() {return m_name;}};#endif //HELLOWORLD_STUDENT_H
//Student.cpp
//
// Created by 陳瑩瑩 on 2021/2/2.
//
#include <iostream>
#include "Student.h"
using namespace std;Student::Student() {cout << "默認構造函數" << endl;InitScores();
}
//Student::Student(string name, string desc){
//    // 參數列表不同,函數重載
//    m_name = name;
//    m_desc = desc;
//    cout << "設置帶參構造" << endl;
//}
//初始化參數列表的寫法,和上上面的帶參數構造方法完全相同
Student::Student(string name, string desc):m_name(name), m_desc(desc){cout << "設置帶參構造" << endl;InitScores();
};void Student::showInfo() {cout << m_desc << m_name << endl;for(int i = 0; i < scoreCount-1; i++){cout << this->scores[i] << "\t";}cout << endl;
}
// C的類方法寫(我這么寫編譯不過)
//void MyShow(const Student* this){
//    this->
//}
void Student::InitScores() {this -> scores = new float [1];this -> scoreCount = 1;
}
void Student::AddScore(float score) {this -> scores[this->scoreCount -1] = score;// 1. 創建一個新數組,分配scoreCount+1 個空間// 2. 復制愿數組中的內容到新數組中// 3. scoreCount++// 4. scores指向新數組float *newScores = new float [scoreCount + 1];float *oldScores = scores;memcpy(newScores, scores, sizeof(float) * scoreCount);scoreCount++;scores = newScores;delete oldScores;    // 刪除原來的指針
}
Student & Student::GetSuperScholars(Student &otherstu){// otherstu 要對比的另一學生對象// 返回總分比較大的那個學生對象// 分別計算兩個學生的總分if(this->GetTotal() > otherstu.GetTotal()){return *this;}else{return otherstu;}}
float Student::GetTotal(){float sum = 0;for(int i = 0; i < scoreCount; i++){sum += scores[i];}return sum;}
Student::~Student() {cout << m_name << "被釋放" << endl;delete this -> scores;}

輸出

設置帶參構造
微胖女孩迪麗熱巴
78.9	77.9	72.9	79.9	800	
設置帶參構造
不愛美人劉強東
78.9	77.9	72.9	79.9	90	
學霸是迪麗熱巴	迪麗熱巴
迪麗熱巴被釋放
劉強東被釋放

小結:類就是自己定義的數據類型,對象就是變量

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/444808.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/444808.shtml
英文地址,請注明出處:http://en.pswp.cn/news/444808.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

終于,我讀懂了所有Java集合——map篇(多線程)

多線程環境下的問題 1.8中hashmap的確不會因為多線程put導致死循環&#xff08;1.7代碼中會這樣子&#xff09;&#xff0c;但是依然有其他的弊端&#xff0c;比如數據丟失等等。因此多線程情況下還是建議使用ConcurrentHashMap。 數據丟失&#xff1a;當多線程put的時候&…

system函數的返回值和執行腳本的返回值

1、先統一兩個說法&#xff1a;&#xff08;1&#xff09;system返回值&#xff1a;指調用system函數后的返回值&#xff0c;比如上例中status為system返回值&#xff08;2&#xff09;shell返回值&#xff1a;指system所調用的shell命令的返回值&#xff0c;比如上例中&#x…

OJ匯總

國內&#xff1a;&#xff08;一下排名不分先后&#xff09; 浙江大學&#xff08;ZJU&#xff09;&#xff1a;http://acm.zju.edu.cn/ 北京大學&#xff08;PKU&#xff09;&#xff1a;http://acm.pku.edu.cn/JudgeOnline/ 同濟大學&#xff08;TJU&#xff09;&#xff1a;…

C++(15)--面向對象編程實踐-歡樂斗地主(vector的花式輸出)

面向對象編程實踐-歡樂斗地主《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》-------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------要求&#xff1a;實現錄入及…

Google Protobuf 使用介紹

直接在 www.google.com.hk 上搜索google protobuf 后下載官方版本。 官方版本支持C\Java\Python三門語言。 還有很多非官方的語言版本支持&#xff0c;如C\NET(C#/Vb.net)\Flex(AS3)等. 要通信&#xff0c;必須有協議&#xff0c;否則雙方無法理解對方的碼流。在protobuf中&…

epoll的再次認識

使用mmap加速內核與用戶空間的消息傳遞。 這 點實際上涉及到epoll的具體實現了。無論是select,poll還是epoll都需要內核把FD消息通知給用戶空間,如何避免不必要的內存拷貝就很 重要,在這點上,epoll是通過內核于用戶空間mmap同一塊內存實現的。而如果你想我一樣從2.5內核就關…

leetcode82. 刪除排序鏈表中的重復元素 II

給定一個排序鏈表&#xff0c;刪除所有含有重復數字的節點&#xff0c;只保留原始鏈表中 沒有重復出現 的數字。 示例 1: 輸入: 1->2->3->3->4->4->5 輸出: 1->2->5 示例 2: 輸入: 1->1->1->2->3 輸出: 2->3 思路&#xff1a;判斷n…

C++(16)--運算符重載(自定義Integer類)

運算符重載1.運算符重載--重點2.友元函數--難點(流運算符重載)《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》 -------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)--------…

反應器組件 ACE_Reactor

6.1 反應器組件 ACE_Reactor反應器的基本原理是: 針對關心的某個事件寫一個事件處理器(event_handler). 將該事件處理器登記到反應器中(同時指明關心的事件). 然后反應器會自動檢測事件的發生. 并調用預先登記的事件處理器中的回調函數. 所以ACE Reactor 框架的責任&#x…

C++(17)--詳解const

詳解const《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》-------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------1.const修飾成員變量 2.const修飾函數參數 3.c…

cppcheck的安裝和使用

首先從這里下載linux版本的:http://sourceforge.net/projects/cppcheck/files/cppcheck/ 然后下載對應的版本,解壓,之后安裝: 編譯: g++ -o cppcheck -Ilib cli/*.cpp lib/*.cpp 安裝: make install

leetcode24 兩兩交換鏈表中的節點

給定一個鏈表&#xff0c;兩兩交換其中相鄰的節點&#xff0c;并返回交換后的鏈表。 你不能只是單純的改變節點內部的值&#xff0c;而是需要實際的進行節點交換。 示例: 給定 1->2->3->4, 你應該返回 2->1->4->3. 思路&#xff1a;這一看就是個遞歸定義&…

再議指針和引用的一些事情吧

關于指針和引用一直是學習C++的同學們爭論的焦點,什么時候用指針,什么時候用引用,還有怎么引用數組,這么用指針訪問數組,以及初始化的問題。 不過有一些文章我在很早就已經寫過,但是由于當時時間不充分,自己也都是隨性寫的,可以參看以前我的一個文章:http://blog.csd…

C++(18)--復制構造函數

復制構造函數《老九學堂C課程》《C primer》學習筆記。《老九學堂C課程》詳情請到B站搜索《老九零基礎學編程C入門》-------------簡單的事情重復做&#xff0c;重復的事情用心做&#xff0c;用心的事情堅持做(老九君)---------------包裝基本類&#xff0c;封裝一些算法。 需求…

lua與C++粘合層框架

一. lua調用C 在lua中是以函數指針的形式調用函數, 并且所有的函數指針都必須滿足如下此種類型: typedef int (*lua_CFunction) (lua_State *L);   也就是說, 偶們在C中定義函數時必須以lua_State為參數, 以int為返回值才能被Lua所調用. 但是不要忘記了, 偶們的lua_State是…

leetcode147 對鏈表進行插入排序

丟人&#xff0c;我就是按插入排序老老實實寫的啊。。。。 別人肯定map了hhh。 對鏈表進行插入排序。 插入排序的動畫演示如上。從第一個元素開始&#xff0c;該鏈表可以被認為已經部分排序&#xff08;用黑色表示&#xff09;。 每次迭代時&#xff0c;從輸入數據中移除一個…

PaperNotes(13)-Conditional Image Generation with PixelCNN Decoders

conditional Image generation with PixelCNN DecodersICML的best paperpixel cnn 屬于完全可見的信念網絡&#xff0c;需要對 概率密度 建模。給定圖像數據x&#xff0c;想要對概率分布p(x)建模。概率分布p(x)可以看做&#xff0c;每一像素分布同時作用結果的一個聯合分布。一…

Expression : invalid operator 解決方法

從技術上說&#xff0c;用于排序關聯容器的比較函數必須在它們所比較的對象上定義一個“嚴格的弱序化(strict weak ordering)”。&#xff08;傳給sort等算法的比較函數也有同樣的限制&#xff09;,就是兩個對象比大小或先后的規則&#xff0c;比如兩個 string對象比大小的規則…

leetcode23 合并K個排序鏈表

合并 k 個排序鏈表&#xff0c;返回合并后的排序鏈表。請分析和描述算法的復雜度。 示例: 輸入: [ 1->4->5, 1->3->4, 2->6 ] 輸出: 1->1->2->3->4->4->5->6 思路&#xff1a;把初始的每一個鏈表當成數組中的一個數&#xff0c;做…

Xcode LaunchImage 載入界面大小設置

iPhone Portrait iOS 8-Retina HD 5.5 (12422208) @3x iPhone Portrait iOS 8-Retina HD 4.7 (7501334) @2x iPhone Portrait iOS 7,8-2x (640960) @2x iPhone Portrait iOS 7,8-Retina 4 (6401136) @2x iPhone Portrait iOS 5,6-1x (320480) @1x iPhone Portrait iO…