C++兼容C語言,所以基礎(chǔ)部分可以 參考C語言基礎(chǔ)快查坎弯。
C++數(shù)據(jù)類型
C++比C的整型多了個布爾類型 布爾型 bool
, bool類型變量占用內(nèi)存1字節(jié)。
C++ 中的類型限定符
限定符 | 說明 |
---|---|
const ? ? ? ? ? ? ? ? ? ? | const 類型的對象在程序執(zhí)行期間不能被修改惩淳。 |
volatile ? ? ? ? ? | 修飾符 volatile 告訴編譯器不需要優(yōu)化volatile聲明的變量揭措,讓程序可以直接從內(nèi)存中讀取變量。對于一般的變量編譯器會對變量進(jìn)行優(yōu)化完慧,將內(nèi)存中的變量值放在寄存器中以加快讀寫效率谋旦。 |
restrict ? ? ? ? ? | 由 restrict 修飾的指針是唯一一種訪問它所指向的對象的方式。只有 C99 增加了新的類型限定符 restrict屈尼。 |
存儲類
mutable
mutable 能用來修飾類的數(shù)據(jù)成員册着,被 mutable 修飾的數(shù)據(jù)成員,可以在 const 成員函數(shù)中修改脾歧。比如const意思是“這個函數(shù)不修改對象內(nèi)部狀態(tài)”甲捏,mutable意思是“這個成員變量不算對象內(nèi)部狀態(tài)”,mutable告訴編譯器修改它并不影響const語義鞭执,所以就不需要禁止const函數(shù)修改它司顿。
thread_local
thread_local 聲明的變量僅可在它在其上創(chuàng)建的線程上訪問。 變量在創(chuàng)建線程時創(chuàng)建兄纺,并在銷毀線程時銷毀大溜。 每個線程都有其自己的變量副本。
- thread_local 說明符可以與 static 或 extern 合并估脆。
- thread_local 僅應(yīng)用于數(shù)據(jù)聲明和定義钦奋,thread_local 不能用于函數(shù)聲明或定義。
// 命名空間下的全局變量
thread_local int x;
class X
{
// 類的static成員變量
static thread_local std::string s;
};
static thread_local std::string X::s; // X::s 是需要定義的
void foo()
{
// 本地變量
thread_local std::vector<int> v;
}
C++ 引用
C++比C多了引用類型疙赠,其實(shí)引用就是給變量的一個別名付材。
- 沒有空引用,引用必須連接到一塊合法的內(nèi)存圃阳。
- 一旦引用被初始化為一個對象厌衔,就不能被指向到另一個對象。
- 引用必須在創(chuàng)建時被初始化捍岳。
int a = 1;
int& ref = a;
那么ref
就是a
富寿,a
也是ref
睬隶。
C++ 函數(shù)
C++ 函數(shù)在C的函數(shù)又增加了為參數(shù)指定默認(rèn)值等特性。
參數(shù)默認(rèn)值
定義函數(shù)時作喘,可以為參數(shù)列表中后邊的每一個參數(shù)指定默認(rèn)值理疙。當(dāng)調(diào)用函數(shù)時,實(shí)參的值留空泞坦,形參就使用這個默認(rèn)值窖贤。
int sum(int a, int b= 1);
int sum(int a = 0, int b = 1);
int sum(int a =0, int b);
這樣不行
引用作為參數(shù)
引用作為參數(shù),函數(shù)內(nèi)部實(shí)際上使用的是實(shí)參贰锁,不會引起形參的拷貝赃梧。
void swap(int& x, int& y)
{
int temp;
temp = x; /* 保存地址 x 的值 */
x = y; /* 把 y 賦值給 x */
y = temp; /* 把 x 賦值給 y */
return;
}
引用作為返回值
static int sum = 0;
int& swap(int& x, int& y)
{
sum = x + y;
return sum;
}
C++ 類 & 對象
面向?qū)ο蟮幕咎卣鳎悍庋b、繼承和多態(tài)豌熄。
C++ 類定義
class People
{
public:
std::string name;
double age;
};
定義 C++ 對象
People people;
數(shù)據(jù)成員訪問
people.name = "XiaoMing";
類成員函數(shù)
類成員函數(shù)聲明:
class People
{
public:
std::string name;
double age;
void run(void);
};
類成員函數(shù)定義:直接在類里面定義
class People
{
public:
std::string name;
double age;
void run(void){
std::out<<"run"<<std::endl;
}
};
類成員函數(shù)定義:在類外定義
類外定義需要使用范圍解析運(yùn)算符::
授嘀, ::的前面是類名,::后面是函數(shù)名
void People::run(void){
std::out<<"run"<<std::endl;
}
類成員函數(shù)調(diào)用:
People people;
people.run();
類訪問修飾符
在修飾數(shù)據(jù)成員或者成員函數(shù)時:
修飾符 | 說明 |
---|---|
public | 公有成員:類內(nèi)外均可訪問 |
private | 私有成員:只有本類或者友元類/函數(shù)可以訪問 |
protected | 保護(hù)成員:本類锣险、友元類/函數(shù)蹄皱、派生類是可訪問的 |
class內(nèi)默認(rèn)訪問權(quán)限是private,struct默認(rèn)訪問權(quán)限是public芯肤。
構(gòu)造函數(shù)
創(chuàng)建新對象時被自動調(diào)用執(zhí)行巷折,函數(shù)名與類的名稱是完全相同的,并且不會返回任何類型崖咨,也不會返回 void锻拘,可以帶參數(shù)。
如果一個類沒有定義任何構(gòu)造函數(shù)击蹲,編譯器會創(chuàng)建合成的默認(rèn)構(gòu)造函數(shù)署拟。
構(gòu)造函數(shù)作用:為某些成員變量設(shè)置初始值。
class People
{
public:
People();//<--構(gòu)造函數(shù)
std::string name;
double age;
void run(void);
};
People people;
帶參數(shù)的構(gòu)造函數(shù)歌豺。
class People
{
public:
People(std::string name);//<--帶參數(shù)的構(gòu)造函數(shù)
std::string name;
double age;
void run(void);
};
People people("XiaoMing");
如果想在自定義其他構(gòu)造函數(shù)的同時保留默認(rèn)的構(gòu)造函數(shù)推穷。在類定義添加默認(rèn)構(gòu)造函數(shù)聲明 = default
即可。
People() = default;
初始化列表
class People
{
public:
People(std::string name):name(name);//<--初始化列表
std::string name;
double age;
void run(void);
};
People people("XiaoMing");
析構(gòu)函數(shù)
對象被銷毀時自動調(diào)用类咧。名稱與類的名稱是完全相同的缨恒,需要前面加了個波浪號(~)作為前綴,不返回任何值轮听,也不帶任何參數(shù)。
主要用來用來在對象銷毀前釋放對象申請的資源岭佳。
class People
{
public:
People();//<--構(gòu)造函數(shù)
~People()血巍;
std::string name;
double age;
void run(void);
};
People people;
拷貝構(gòu)造函數(shù)
創(chuàng)建對象可以使用一個存在的對象初始化新對象。
- 如果類中沒有定義拷貝構(gòu)造函數(shù)珊随,編譯器會自行定義一個述寡。
- 如果類帶有指針變量柿隙,并有動態(tài)內(nèi)存分配,則它必須有一個拷貝構(gòu)造函數(shù)鲫凶。
class People
{
public:
People();//<--構(gòu)造函數(shù)
People(const People& aPeople){
}
~People()禀崖;
std::string name;
double age;
void run(void);
};
People people;
People other = People(people);
友元函數(shù)
類的友元函數(shù)是定義在類外部,聲明在類的內(nèi)部螟炫,表示這個外部函數(shù)可以訪問類的保護(hù)和私有成員波附。
友元函數(shù)不是成員函數(shù)。
class People
{
public:
People();
friend void sayHello( People &people );
~People()昼钻;
std::string name;
double age;
void run(void);
};
this 指針
對象使用 this 指針來訪問自己的地址掸屡,自有成員函數(shù)才有 this 指針。
class People
{
public:
People();
~People()然评;
std::string name;
double age;
void setName(std::string name){
this->name = name;
}
};
指向類的指針
指向類的指針和指向結(jié)構(gòu)體的指針一致仅财。可以使用成員訪問運(yùn)算符 ->來訪問成員碗淌,或者解引用*
的方式引用指針盏求。
People tom = People();
People *ptr = &tom;
std::cout>>ptr->name>>std::endl;
std::cout>>(*ptr).name>>std::endl;
類的靜態(tài)成員
static 把類成員定義為靜態(tài)成員。
- 包括靜態(tài)成員變量和靜態(tài)成員函數(shù)亿眠。
- 靜態(tài)成員變量只存在一份碎罚,普通成員和靜態(tài)成員函數(shù)都可訪問靜態(tài)成員變量。
- 靜態(tài)成員函數(shù)可以訪問靜態(tài)成員變量缕探,不能直接訪問類普通成員魂莫,沒有this指針。
// People.h
class People
{
public:
People();
~People()爹耗;
std::string name;
double age;
static std::string className;
static std::string &getClassName(){
return className;
}
};
靜態(tài)成員變量的初始化在類外面進(jìn)行
//People.cpp
std::string People::className = "People";
外部使用位運(yùn)算符::
訪問
std::cout<<People::className<<std::end;
std::cout<<People::getClassName()<<std::end;
繼承
使用已有的類定義新的類耙考,新的類含有原來類的成員的同時,可以創(chuàng)建新的新的成員潭兽。
已有的類稱為基類倦始,新建的類稱為派生類。
繼承的格式
class 派生類: 訪問控制符 基類
class People
{
public:
People();
~People()山卦;
std::string name;
double age;
void setName(std::string name){
this->name = name;
}
};
class Chinese: public People{
public:
std::string id_number;
}
繼承訪問控制符
繼承不寫訪問控制符:
- class 的默認(rèn)繼承方式是: private
- struct 的默認(rèn)繼承方式是:public
派生類繼承了所有的基類方法鞋邑,下列情況除外:
- 基類的構(gòu)造函數(shù)、析構(gòu)函數(shù)和拷貝構(gòu)造函數(shù)账蓉。
- 基類的重載運(yùn)算符枚碗。
- 基類的友元函數(shù)。
public繼承:(最大public)
public成員是pulic的铸本,protected成員是protected的肮雨,private成員無法繼承。
protected繼承:(最大protected)
public成員是protected的箱玷,protected成員是protected的怨规,private成
員無法繼承陌宿。
private繼承:(最大private)
public成員是private的,protected成員是private的波丰,private成員無法繼承壳坪。
多繼承
多繼承格式:
class 派生類: 訪問控制符 基類1, 訪問控制符 基類2, 訪問控制符 基類3, ...
多個基類中含有同名函數(shù),會產(chǎn)生二義性掰烟,在訪問時可以加上域控制符:
#include <iostream>
using namespace std;
class classA{
public:
void func (int aInt){
cout<<"classA::func"<<aInt<<endl;
}
void func (char aChar){
cout<<"classA::func"<<aChar<<endl;
}
};
class classB{
public:
void func (double aDouble){
cout<<"classB::func"<<aDouble<<endl;
}
};
class classC: public classA, public classB{
public:
using classA::func;
using classB::func;
};
int main(int argc, const char * argv[]) {
classC obj = classC();
obj.func('a'); // 這里無法編譯通過
obj.classA::func('a');
obj.classA::func(1.1);
return 0;
}
或者在派生類中通過using聲明爽蝴,把基類中的同名函數(shù)都引入到一個公共域中,這樣重載解析規(guī)則就可以正常使用媚赖。
class classC: public classA, public classB{
public:
using classA::func; //!!!!
using classB::func;
};
int main(int argc, const char * argv[]) {
classC obj = classC();
obj.func('a'); // 這里就可以了
return 0;
}
但是如果基類包含一模一樣函數(shù)使用using是無法編譯通過的霜瘪。
多態(tài)
通過繼承關(guān)系為不同的類的實(shí)體提供統(tǒng)一的接口。使用接口調(diào)用時惧磺,會根據(jù)調(diào)用函數(shù)的對象的類型來執(zhí)行不同的函數(shù)颖对。
C++通過關(guān)鍵字virtual
實(shí)現(xiàn)繼承的多態(tài)。
虛函數(shù) :在基類中使用 virtual 聲明的函數(shù)磨隘。派生類中重新定義基類中定義的虛函數(shù)時缤底,會告訴編譯器不要靜態(tài)鏈接到該函數(shù);
class People{
public:
virtual void sayHello(){
cout<<"I am people"<<endl;
}
};
class Student: public People{
public:
void sayHello(){
cout<<"I am Studenmt"<<endl;
}
};
class Teacher: public People{
public:
void sayHello(){
cout<<"I am Teacher"<<endl;
}
};
int main(int argc, const char * argv[]) {
People *ptr = NULL;
Student student;
Teacher teacher;
ptr = &student;
ptr->sayHello();
ptr = &teacher;
ptr->sayHello();
return 0;
}
運(yùn)行結(jié)果如下:
I am Studenmt
I am Teacher
如果基類的sayHello不使用virtual修飾番捂,那么main函數(shù)中的指針ptr時靜態(tài)綁定的个唧,指向派生類對象的基類的方法。
比如把sayHello的virtual去掉:
class People{
public:
void sayHello(){
cout<<"I am people"<<endl;
}
};
結(jié)果如下设预,都是運(yùn)行的基類的方法:
I am people
I am people
如果在基類中定義虛函數(shù)徙歼,但不想在基類中實(shí)現(xiàn)該函數(shù),就可以使用純虛函數(shù)鳖枕,如果魄梯。
virtual void sayHello() = 0;
含有純虛函數(shù)的類叫做抽象類,如果它的派生類不實(shí)現(xiàn)基類中的純虛函數(shù)宾符,那么這個派生類也是抽象類酿秸。抽象類不能定義對象。
重載魏烫、重寫(覆蓋)辣苏、隱藏
重載 overload
同一作用域中,同名函數(shù)的形式參數(shù)(參數(shù)個數(shù)哄褒、類型或者順序)不同時稀蟋,構(gòu)成函數(shù)重載。
- 函數(shù)返回值類型與構(gòu)成重載無任何關(guān)系呐赡。
- 類的靜態(tài)成員函數(shù)與普通成員函數(shù)可以形成重載糊治。
- 函數(shù)重載發(fā)生在同一作用域,如類成員函數(shù)之間的重載罚舱、全局函數(shù)之間的重載井辜。