c++基础学习(07)--(类)
文章目錄
- 目錄
- 類與對象
- 1.類成員函數
- 2.類訪問修飾符
- 3.構造函數與析構函數
- 4.拷貝構造函數
- 5. 友元函數
- 6.內聯函數
- 7.this指針
- 8.指向類的指針
- 9.類的靜態成員
目錄
類與對象
當上面的代碼被編譯和執行時,它會產生下列結果:
Box1 的體積:210
Box2 的體積:1560
需要注意的是,私有的成員和受保護的成員不能使用直接成員訪問運算符 (.) 來直接訪問.
1.類成員函數
當上面的代碼被編譯和執行時,它會產生下列結果:
Box1 的體積: 210
Box2 的體積: 1560
2.類訪問修飾符
公有成員Public
公有成員在程序中類的外部是可訪問的。您可以不使用任何成員函數來設置和獲取公有變量的值,如下所示:
當上面的代碼被編譯和執行時,它會產生下列結果:
Length of line : 6
Length of line : 10
私有成員Private
私有成員變量或函數在類的外部是不可訪問的,甚至是不可查看的。只有類和友元函數可以訪問私有成員。
默認情況下,類的所有成員都是私有的。例如在下面的類中,width 是一個私有成員,這意味著,如果您沒有使用任何訪問修飾符,類的成員將被假定為私有成員:
實際操作中,我們一般會在私有區域定義數據,在公有區域定義相關的函數,以便在類的外部也可以調用這些函數,如下所示:
#include <iostream>using namespace std;class Box {public:double length;void setWidth( double wid );double getWidth( void );private:double width; };// 成員函數定義 double Box::getWidth(void) {return width ; }void Box::setWidth( double wid ) {width = wid; }// 程序的主函數 int main( ) {Box box;// 不使用成員函數設置長度box.length = 10.0; // OK: 因為 length 是公有的cout << "Length of box : " << box.length <<endl;// 不使用成員函數設置寬度// box.width = 10.0; // Error: 因為 width 是私有的box.setWidth(10.0); // 使用成員函數設置寬度cout << "Width of box : " << box.getWidth() <<endl;return 0; }當上面的代碼被編譯和執行時,它會產生下列結果:
Length of box : 10
Width of box : 10
保護成員Protected
保護成員變量或函數與私有成員十分相似,但有一點不同,保護成員在派生類(即子類)中是可訪問的。
在下一個章節中,您將學習到派生類和繼承的知識。現在您可以看到下面的實例中,我們從父類 Box 派生了一個子類 smallBox。
下面的實例與前面的實例類似,在這里 width 成員可被派生類 smallBox 的任何成員函數訪問。
10
1
sh: 1: pause: not found
protected 繼承
#include<iostream> #include<assert.h> using namespace std; class A{ public:int a;A(){a1 = 1;a2 = 2;a3 = 3;a = 4;}void fun(){cout << a << endl; //正確cout << a1 << endl; //正確cout << a2 << endl; //正確cout << a3 << endl; //正確} public:int a1; protected:int a2; private:int a3; }; class B : protected A{ public:int a;B(int i){A();a = i;}void fun(){cout << a << endl; //正確,public成員。cout << a1 << endl; //正確,基類的public成員,在派生類中變成了protected,可以被派生類訪問。cout << a2 << endl; //正確,基類的protected成員,在派生類中還是protected,可以被派生類訪問。cout << a3 << endl; //錯誤,基類的private成員不能被派生類訪問。} }; int main(){B b(10);cout << b.a << endl; //正確。public成員cout << b.a1 << endl; //錯誤,protected成員不能在類外訪問。cout << b.a2 << endl; //錯誤,protected成員不能在類外訪問。cout << b.a3 << endl; //錯誤,private成員不能在類外訪問。system("pause");return 0; }private 繼承
#include<iostream> #include<assert.h> using namespace std; class A{ public:int a;A(){a1 = 1;a2 = 2;a3 = 3;a = 4;}void fun(){cout << a << endl; //正確cout << a1 << endl; //正確cout << a2 << endl; //正確cout << a3 << endl; //正確} public:int a1; protected:int a2; private:int a3; }; class B : private A{ public:int a;B(int i){A();a = i;}void fun(){cout << a << endl; //正確,public成員。cout << a1 << endl; //正確,基類public成員,在派生類中變成了private,可以被派生類訪問。cout << a2 << endl; //正確,基類的protected成員,在派生類中變成了private,可以被派生類訪問。cout << a3 << endl; //錯誤,基類的private成員不能被派生類訪問。} }; int main(){B b(10);cout << b.a << endl; //正確。public成員cout << b.a1 << endl; //錯誤,private成員不能在類外訪問。cout << b.a2 << endl; //錯誤, private成員不能在類外訪問。cout << b.a3 << endl; //錯誤,private成員不能在類外訪問。system("pause");return 0; }3.構造函數與析構函數
#include <iostream>using namespace std;class Line {public:void setLength( double len );double getLength( void );Line(); // 這是構造函數private:double length; };// 成員函數定義,包括構造函數 Line::Line(void) {cout << "Object is being created" << endl; }void Line::setLength( double len ) {length = len; }double Line::getLength( void ) {return length; } // 程序的主函數 int main( ) {Line line;// 設置長度line.setLength(6.0); cout << "Length of line : " << line.getLength() <<endl;return 0; }當上面的代碼被編譯和執行時,它會產生下列結果:
Object is being created
Length of line : 6
帶參數的構造函數
默認的構造函數沒有任何參數,但如果需要,構造函數也可以帶有參數。這樣在創建對象時就會給對象賦初始值,如下面的例子所示:
當上面的代碼被編譯和執行時,它會產生下列結果:
Object is being created, length = 10
Length of line : 10
Length of line : 6
類的析構函數
類的析構函數是類的一種特殊的成員函數,它會在每次刪除所創建的對象時執行。
析構函數的名稱與類的名稱是完全相同的,只是在前面加了個波浪號(~)作為前綴,它不會返回任何值,也不能帶有任何參數。析構函數有助于在跳出程序(比如關閉文件、釋放內存等)前釋放資源。
下面的實例有助于更好地理解析構函數的概念:
當上面的代碼被編譯和執行時,它會產生下列結果:
Object is being created
Length of line : 6
Object is being deleted
4.拷貝構造函數
#include <iostream>using namespace std;class Line {public:int getLength( void );Line( int len ); // 簡單的構造函數Line( const Line &obj); // 拷貝構造函數~Line(); // 析構函數private:int *ptr; };// 成員函數定義,包括構造函數 Line::Line(int len) {cout << "調用構造函數" << endl;// 為指針分配內存ptr = new int;*ptr = len; }Line::Line(const Line &obj) {cout << "調用拷貝構造函數并為指針 ptr 分配內存" << endl;ptr = new int;*ptr = *obj.ptr; // 拷貝值 }Line::~Line(void) {cout << "釋放內存" << endl;delete ptr; } int Line::getLength( void ) {return *ptr; }void display(Line obj) {cout << "line 大小 : " << obj.getLength() <<endl; }// 程序的主函數 int main( ) {Line line(10);display(line);return 0; }當上面的代碼被編譯和執行時,它會產生下列結果:
調用構造函數
調用拷貝構造函數并為指針 ptr 分配內存
line 大小 : 10
釋放內存
釋放內存
下面的實例對上面的實例稍作修改,通過使用已有的同類型的對象來初始化新創建的對象:
#include <iostream>using namespace std;class Line {public:int getLength( void );Line( int len ); // 簡單的構造函數Line( const Line &obj); // 拷貝構造函數~Line(); // 析構函數private:int *ptr; };// 成員函數定義,包括構造函數 Line::Line(int len) {cout << "調用構造函數" << endl;// 為指針分配內存ptr = new int;*ptr = len; }Line::Line(const Line &obj) {cout << "調用拷貝構造函數并為指針 ptr 分配內存" << endl;ptr = new int;*ptr = *obj.ptr; // 拷貝值 }Line::~Line(void) {cout << "釋放內存" << endl;delete ptr; } int Line::getLength( void ) {return *ptr; }void display(Line obj) {cout << "line 大小 : " << obj.getLength() <<endl; }// 程序的主函數 int main( ) {Line line1(10);Line line2 = line1; // 這里也調用了拷貝構造函數display(line1);display(line2);return 0; }當上面的代碼被編譯和執行時,它會產生下列結果:
調用構造函數
調用拷貝構造函數并為指針 ptr 分配內存
調用拷貝構造函數并為指針 ptr 分配內存
line 大小 : 10
釋放內存
調用拷貝構造函數并為指針 ptr 分配內存
line 大小 : 10
釋放內存
釋放內存
釋放內存
5. 友元函數
#include <iostream>using namespace std;class Box {double width; public:friend void printWidth( Box box );void setWidth( double wid ); };// 成員函數定義 void Box::setWidth( double wid ) {width = wid; }// 請注意:printWidth() 不是任何類的成員函數 void printWidth( Box box ) {/* 因為 printWidth() 是 Box 的友元,它可以直接訪問該類的任何成員 */cout << "Width of box : " << box.width <<endl; }// 程序的主函數 int main( ) {Box box;// 使用成員函數設置寬度box.setWidth(10.0);// 使用友元函數輸出寬度printWidth( box );return 0; }當上面的代碼被編譯和執行時,它會產生下列結果:
Width of box : 10
6.內聯函數
#include <iostream>using namespace std;inline int Max(int x, int y) {return (x > y)? x : y; }// 程序的主函數 int main( ) {cout << "Max (20,10): " << Max(20,10) << endl;cout << "Max (0,200): " << Max(0,200) << endl;cout << "Max (100,1010): " << Max(100,1010) << endl;return 0; }當上面的代碼被編譯和執行時,它會產生下列結果:
Max (20,10): 20
Max (0,200): 200
Max (100,1010): 1010
7.this指針
#include <iostream>using namespace std;class Box {public:// 構造函數定義Box(double l=2.0, double b=2.0, double h=2.0){cout <<"Constructor called." << endl;length = l;breadth = b;height = h;}double Volume(){return length * breadth * height;}int compare(Box box){return this->Volume() > box.Volume();}private:double length; // Length of a boxdouble breadth; // Breadth of a boxdouble height; // Height of a box };int main(void) {Box Box1(3.3, 1.2, 1.5); // Declare box1Box Box2(8.5, 6.0, 2.0); // Declare box2if(Box1.compare(Box2)){cout << "Box2 is smaller than Box1" <<endl;}else{cout << "Box2 is equal to or larger than Box1" <<endl;}return 0; }當上面的代碼被編譯和執行時,它會產生下列結果:
Constructor called.
Constructor called.
Box2 is equal to or larger than Box1
8.指向類的指針
一個指向 C++ 類的指針與指向結構的指針類似,訪問指向類的指針的成員,需要使用成員訪問運算符 ->,就像訪問指向結構的指針一樣。與所有的指針一樣,您必須在使用指針之前,對指針進行初始化。
下面的實例有助于更好地理解指向類的指針的概念:
當上面的代碼被編譯和執行時,它會產生下列結果:
Constructor called.
Constructor called.
Volume of Box1: 5.94
Volume of Box2: 102
9.類的靜態成員
我們可以使用 static 關鍵字來把類成員定義為靜態的。當我們聲明類的成員為靜態時,這意味著無論創建多少個類的對象,靜態成員都只有一個副本。
靜態成員在類的所有對象中是共享的。如果不存在其他的初始化語句,在創建第一個對象時,所有的靜態數據都會被初始化為零。我們不能把靜態成員的初始化放置在類的定義中,但是可以在類的外部通過使用范圍解析運算符 :: 來重新聲明靜態變量從而對它進行初始化,如下面的實例所示。
下面的實例有助于更好地理解靜態成員數據的概念:
當上面的代碼被編譯和執行時,它會產生下列結果:
Constructor called.
Constructor called.
Total objects: 2
當上面的代碼被編譯和執行時,它會產生下列結果:
Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2
靜態成員變量在類中僅僅是聲明,沒有定義,所以要在類的外面定義,實際上是給靜態成員變量分配內存。如果不加定義就會報錯,初始化是賦一個初始值,而定義是分配內存。
總結
以上是生活随笔為你收集整理的c++基础学习(07)--(类)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 机器学习中的距离和损失函数
- 下一篇: 《Python Cookbook 3rd