一.C++類與對象
1.基本單位是類。
2.類是數據和操作數據的函數的封裝。
3.對象使用自己的方法完成對數據的操作。
4.類可以隱藏數據和操作細節,對象通過類結構與外部通信。
C++與C進行代碼重用是通過類和函數來實現的。C++同時可以通過類來限定數據訪問得的權限。
C++通過類的繼承實現代碼重用,類的封裝實現權限封裝,數據與代碼合爲一體。類的多態實現一個接口的多個功能。通過接口封裝實現不同的權限。
類中包含三種類型的數據: private 私有數據類型 protected 保護類型 private 私有類型
1>三種類型的訪問權限:
private | protected | public |
私有數據類型盡在類中可見 | 在該類和派生類中可見 | 提供外部的接口,外部可訪問的數據及方法 |
class | struct | union |
默認下爲私有數據類型和方法 | 默認情況下爲公有public | 默認情況下爲公有public |
1.允許已定義的類名出現在累的說明中。
2.類可以無名,用於直接申明對象。
3.類是一個程序包,可以只有數據成員或函數,或者爲空,空類的對象大小不爲零,空類佔一個字節,表明類存在。空類中函數在代碼區,不包括函數,大小佔一個字節。
#include<iostream>
class kong
{
public:
//int num;
void go(int num)
{
std::cout << "12345" << std::endl;
}
};
void main()
{
kong kong1;
//kong1.num = 100;
//std::cout << sizeof(kong) << std::endl; 空類佔用一個字節,表明類存在,代碼不計入sizeof
std::cout << sizeof(kong) << std::endl;
std::cout << &kong1<< std::endl;
std::cin.get();
}
4.類中包含常量數據以及常量函數的情況
class myclass1
{
public:
int a;
const int b=0;//常量必須進行初始化
mutable int e;//不被const限制.
//限定不對成員變量賦值,但是可以對mutable數據賦值,
void set(int a) const
{
}
};
三.構造函數與析構函數
作用:分配空間,爲對象成員賦值,請求其他資源
1.所有類都默認有一個構造函數,一個析構函數和拷貝構造函數。
2.構造函數和析構函數都可以重載,且沒有返回值。
#include<iostream>
class myclass
{
public:
int num;
public:
//構造函數與析構函數的重載
myclass():num(4) //變量初始化方式二
{
//num = 4;變量 初始化方式1,
std::cout << "對象被建立"<<std::endl;
}
myclass(int a) //構造函數的重載
{
this->num = a;
}
~myclass()
{
std::cout << "對象被銷燬"<<std::endl;
}
};
void run()
{
myclass classa,classb(8);//等價於classb=10;
std::cout << classa.num << " " << classb.num << std::endl;
}
void main1()
{
myclass *p = new myclass(10); //等價於*p=(new myclass(10))
p = new myclass(100);
run();
int num = 4;
int data(4);//調用int類型的構造函數
std::cin.get();
}
3.類中包含其他類時,所包含的類首先創建,然後該類創建。銷燬時,該類先銷燬,所包含的類後銷燬。#include<iostream>
//系統自動生成
class fushu
{
public:
fushu();
~fushu();
};
fushu::fushu()
{
std::cout << "fushu類的構造" << std::endl;
}
fushu::~fushu()
{
std::cout << "fushu類的銷燬" << std::endl;
}
class math
{
public:
fushu fushu1;
math()
{
std::cout << "math類的構造" << std::endl;
}
~math()
{
std::cout << "math類的銷燬" << std::endl;
}
};
void go()
{
math math1;
}
void main2()
{
go();//類創建過程:fushu類先創建,math類創建, 類銷燬過程:math先銷燬,然後fushu銷燬
std::cin.get();
}
4.explicit 顯式調用,不允許進行隱式類型轉換。
#include<iostream>
#include<array>
#include<vector>
class classobj
{
public:
int num;
public:
explicit classobj(int data)
{
this->num = data;
std::cout << "類的創建以及數據初始化"<<num << std::endl;
}
~classobj()
{
std::cout << "被銷燬" << num << std::endl;
}
protected:
private:
};
void main()
{
//classobj num = 5;//賦值號,類型轉換
classobj data(5);// 創建對象必須選擇合適的構造函數
//classobj class1[10];
//classobj *p = new classobj;
//classobj *p = new classobj(5);
//classobj *p = new classobj(5);
classobj obj(5);
std::array<classobj, 2> arg = {data,obj};
std::vector<classobj> arg1;
arg1.push_back(obj);
std::cin.get();
}
5.拷貝構造函數
1>類會默認生成,可以通過delete與default刪除和生成默認的構造函數和拷貝構造函數。禁用拷貝構造函數,禁止別人拷貝數據。同時類還重載了“=”賦值運算符。
#include<iostream>
class classA
{
private:
int a;
int b;
public:
//classA(const classA & ca) //拷貝函數,如果沒有定義,則自動生成
//{
//}
classA()
{
}
classA(int x,int y):a(x),b(y)//構造函數
{
/*a = x;
b = y;*/
}
void print()
{
std::cout << a << ' ' << b << std::endl;
}
};
void main1()
{ /*編譯器會默認生成默認構造函數和默認拷貝構造函數*/
classA class1(7,8);
classA class2(class1);
class1.print();
class2.print();
std::cin.get();
}
class myclassA
{
public:
//myclassA() = delete; //刪除默認構造函數
myclassA() = default;//默認生成構造函數
myclassA(const myclassA & )=delete;//刪除默認拷貝構造函數
//~myclassA();
};
void main2()
{
myclassA myclass1;
}
2>深度拷貝構造與淺拷貝構造淺拷貝,兩個指針指向同一片內存,對內存中的值進行更新。深拷貝,重新申請內存,將傳遞過來的數據存儲在新的內存中。
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<string>
class string
{
public:
char *p;
int length;
//獲取內容,分配內存,拷貝內容
string(int num,char *str)
{
length = num;
p = new char[length];
memset(p, 0, length);
strcpy(p,str);
}
string(const string &string1)
{ //淺拷貝
//this->p = string1.p;
//this->length = string1.length;
//深拷貝,重新申請內存,將內容拷貝到新的內存空間中,被拷貝的內存空間被銷燬,不影響目前的內存空間
this->length = string1.length;
this->p = new char[this->length];
memset(p, 0, length);
strcpy(this->p,string1.p); //字符串的拷貝
}
~string()
{
delete[]p;//銷燬內存
}
};
void main()
{
string str1(10,"hello!");
string str2(str1);
std::cout << str1.p << std::endl;
std::cout << str2.p << std::endl;
string *pstr = new string(10, "hello!");
string *pstrr = new string(*pstr);
delete pstr;
std::cout << pstrr->p << std::endl; //(*pstr).p
std::cin.get();
}