国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

C++面向?qū)ο蟪绦蛟O(shè)計-北京大學-郭煒【課程筆記(三)】

這篇具有很好參考價值的文章主要介紹了C++面向?qū)ο蟪绦蛟O(shè)計-北京大學-郭煒【課程筆記(三)】。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

開始課程:P7 2_2. 構(gòu)造函數(shù)
課程鏈接:程序設(shè)計與算法(三)C++面向?qū)ο蟪绦蛟O(shè)計 北京大學 郭煒
課程PPT:github提供的對應(yīng)課程PPT

1、構(gòu)造函數(shù)(constructor)

1.1、基本概念

1、成員函數(shù)的一種

  • 名字與類名相同,可以有參數(shù),不能有返回值(void 也不行)
  • 作用是對對象進行初始化,如給成員變量賦初值
  • 如果定義類時沒寫構(gòu)造函數(shù),則編譯器生成一個默認的無參數(shù)的構(gòu)造函數(shù)
    • 默認構(gòu)造函數(shù)無參數(shù),不做任何操作
  • 如果定義了構(gòu)造韓素,則編譯器不生成默認的無參數(shù)的構(gòu)造函數(shù)
  • 對象生成時,構(gòu)造函數(shù)自動調(diào)用。對象一旦生成,就再也不能在其上執(zhí)行構(gòu)造函數(shù)
  • 一個類可以有多個構(gòu)造函數(shù)

2、為什么需要構(gòu)造函數(shù)

  • 構(gòu)造函數(shù)執(zhí)行必要的初始化工作,有了構(gòu)造函數(shù),就不必再寫初始化函數(shù),也不用擔心忘記調(diào)用初始化函數(shù)。
  • 有時對象沒被初始化就使用,會導致程序出錯。

例1:

// 類中沒有寫構(gòu)造函數(shù)
class Complex{
	private:
		double real, imag;
	public:
		void Set(double r, double i);
};  // 編譯器自動生成默認構(gòu)造函數(shù)

Complex c1; // 默認構(gòu)造函數(shù)被調(diào)用
Complex * pc = new Complex; // 默認構(gòu)造函數(shù)被調(diào)用

例2:

class Complex{
	private:
		double real, imag;
	pubilc:
		Complex(double r, double i = 0);  // 構(gòu)造函數(shù)
}
Complex::Complex(double r, double i){
	real = r; imag = i;
}

Complex c1;  //error,缺少構(gòu)造函數(shù)的參數(shù)
Complex * pc = new Complex;  // error,沒有參數(shù)
Complex c1(2);  // OK
Complex c1(2,4), c2(3,5);
Complex * pc = new Complex(3,4);

例3:可以有多個構(gòu)造函數(shù),參數(shù)個數(shù)或類型不同

class Complex{
	private:
		double real, imag;
	pubilc:
		// 函數(shù)重載
		Complex(double r, double i = 0);  // 構(gòu)造函數(shù)
		Complex(double r, double i);
		Complex(double r);
		Complex(Complex c1, Complex c2);
}
Complex::Complex(double r){
	real = r; imag = 0;
}
Complex::Complex(double r, double i){
	real = r; imag = i;
}
Complex::Complex(Complex c1, Complex c2){
	real = c1.real + c2.real;
	imag = c1.imag + c2.imag;
}

// 構(gòu)造函數(shù)初始化
Complex c1(3), c2(1,0), c3(c1,c2);
// c1 = {3, 0}, c2 = {1, 0}, c3 = {4, 0};

例4-1:構(gòu)造函數(shù)在數(shù)組中的使用

#include<iostream>

class CSample
{
    int x;
    public:
        CSample()
        {
            std::cout << "Constructor  1 Called" << std::endl;
        }
        CSample(int n)
        {
            x = n;
            std::cout << "x = " << x << std::endl;
            std::cout << "Constructor 2 Called" << std::endl;
            std::cout << "====================" << std::endl;
        }
};

int main()
{
    CSample array1[2];   // 無參數(shù)構(gòu)造函數(shù)會被調(diào)用兩次
    std::cout << "step1" << std::endl;
    CSample array2[2] = {4, 5};
    std::cout << "step2" << std::endl;
    CSample array3[2] = {3};  // array3[0]:用的是有參構(gòu)造函數(shù)初始化;array3[1]:用的是無參構(gòu)造函數(shù)初始化;
    std::cout << "step3" << std::endl;
    CSample * array4 = new CSample[2];
    delete []array4;

    return 0;
}
// OUT
Constructor  1 Called
Constructor  1 Called
step1
x = 4
Constructor 2 Called
x = 5
Constructor 2 Called
step2
x = 3
Constructor 2 Called
Constructor  1 Called
step3
Constructor  1 Called
Constructor  1 Called
zhangbushi@zhangbushideair beida_lesson % g++ 04.cpp -o 04
zhangbushi@zhangbushideair beida_lesson % ./04            
Constructor  1 Called
Constructor  1 Called
step1
x = 4
Constructor 2 Called
====================
x = 5
Constructor 2 Called
====================
step2
x = 3
Constructor 2 Called
====================
Constructor  1 Called
step3
Constructor  1 Called
Constructor  1 Called

例4-2:構(gòu)造函數(shù)在數(shù)組中的使用

class Test
{
	public:
		Test(int n) {}          //(1)
		Test(int n, int m) {}   //(2)
		Test() {}               //(3)             
};

Test array1[3] = {1, Test(1,2)};
// 三個元素分別(1),(2),(3)初始化

Test array2[3] = {Test(2,3), Test(1,2), 1};
// 三個元素分別用(2),(2),(1)初始化

Test * pArray[3] = {new Test(4), new Test(1,2)};  // new的返回值是指針類型
//兩個元素分別用(1),(2)初始化

2、賦值構(gòu)造函數(shù)

2.1、基本概念

? 只有一個參數(shù),即對同類對象的引用。
? 形如 X::X( X& )X::X(const X &), 二者選一,后者能以常量對象作為參數(shù)
? 如果沒有定義復制構(gòu)造函數(shù),那么編譯器生成默認復制構(gòu)造函數(shù)。默認的復制構(gòu)造函數(shù)完成復制功能。
? 注意事項:無參構(gòu)造函數(shù)不一定存在,但賦值構(gòu)造函數(shù)一定存在;

例1:

class Complex
{
	private:
		double real, imag;
};
Complex c1; //調(diào)用缺省無參構(gòu)造函數(shù)
Complex c2(c1);//調(diào)用缺省的復制構(gòu)造函數(shù),將 c2 初始化成和c1一樣

如果定義的自己的復制構(gòu)造函數(shù),則默認的復制構(gòu)造函數(shù)不存在。

class Complex {
    public :
        double real,imag;
    Complex(){ }
    Complex( const Complex & c ) {
        real = c.real;
        imag = c.imag;
        cout << “Copy Constructor called”;
    }
}; 
Complex c1; 
Complex c2(c1);//調(diào)用自己定義的復制構(gòu)造函數(shù),輸出 Copy Constructor called

不允許有形如 X::X( X )的構(gòu)造函數(shù)。(必須要加上引用)

class CSample {
	CSample( CSample c ) {
	} //錯,不允許這樣的構(gòu)造函數(shù)
};

2.1、復制構(gòu)造函數(shù)起作用的三種情況

  • 1、當用一個對象去初始化同類的另一個對象時。
Complex c2(c1);
Complex c2 = c1; //初始化語句,非賦值語句
  • 2、如果某函數(shù)有一個參數(shù)是類 A 的對象,那么該函數(shù)被調(diào)用時,類A的復制構(gòu)造函數(shù)將被調(diào)用。
class A 
{
	public:
		A() { };
		A( A & a) { 
		cout << "Copy constructor called" <<endl;
		}
};

void Func(A a1){ }
int main(){
	A a2;      // 通過無參構(gòu)造函數(shù)初始化
	Func(a2);  // 調(diào)用復制構(gòu)造函數(shù)(復制構(gòu)造函數(shù),形參是實參的拷貝,不一定)
	return 0;
}
// 程序輸出結(jié)果為: Copy constructor called
  • 3、如果函數(shù)的返回值是類A的對象時,則函數(shù)返回時,A的復制構(gòu)造函數(shù)被調(diào)用:
# include <iostream>
class A 
{
	 public:
 		int v;
 		A(int n) { v = n; };
 		A( const A & a) 
        { 
		    v = a.v;
 			std::cout << "Copy constructor called" << std::endl;
		}
};

A Func() 
{ 
	A b(4);   // 調(diào)用A(int n) { v = n; };  v = 4
	return b; 
}
int main() 
{ 
	std::cout << Func().v << std::endl; 
	return 0; 
}

// 輸出結(jié)果:
Copy constructor called
4
  • 4、注意:對象之間復制并不導致復制構(gòu)造函數(shù)被調(diào)用
#include<iostream>

class CMyclass 
{
    public:
        int n;
        CMyclass() {};
        CMyclass( CMyclass & c) { n = 2 * c.n ;}
};

int main()
{
    CMyclass c1, c2;
    c1.n = 5; 
    c2 = c1;   // 對象間賦值
    CMyclass c3(c1); // 調(diào)用復制構(gòu)造函數(shù)
    std::cout << "c2.n = " << c2.n << ",";
    std::cout << "c3.n = " << c3.n << std::endl;

    return 0; 
}
// 輸出
c2.n = 5,c3.n = 10

2.2、常引用參數(shù)的使用

void fun(CMyclass obj_). {cout << “fun” << endl; }

  • 這樣的函數(shù),調(diào)用時生成形參會引發(fā)復制構(gòu)造函數(shù)調(diào)用,開銷比較大。
  • 所以考慮使用CMyclass & 引用類型作為參數(shù)
  • 如果希望確保實參的值在函數(shù)中不應(yīng)該被改變,那么可以加上const關(guān)鍵字

3、類型轉(zhuǎn)換構(gòu)造函數(shù)

3.1、什么事類型轉(zhuǎn)換構(gòu)造函數(shù)

  • 定義轉(zhuǎn)換構(gòu)造函數(shù)的目的是實現(xiàn)類型的自動轉(zhuǎn)換。
  • 只有一個參數(shù),而且不是復制構(gòu)造函數(shù)的構(gòu)造函數(shù),一般就可以看作是轉(zhuǎn)換構(gòu)造函數(shù)。
  • 當需要的時候,編譯系統(tǒng)會自動調(diào)用轉(zhuǎn)換構(gòu)造函數(shù),建立一個無名的臨時對象(或臨時變量)。

實例:

#include<iostream>

class Complex
{
    public:
        double real, imag;
        Complex( int i )   // (1)
        {
            std::cout << "IntConstructor called" << std::endl;
            real = i; imag = 0;
        }
        Complex(double r, double i) {real =r; imag = i;}    //(2)
};

int main ()
{
    Complex c1(7, 8);
    Complex c2 = 12;
    c1 = 9;   // 解釋如下
    /*
    c1 = 9; 解釋如下
    1、首先9會被自動轉(zhuǎn)化成一個臨時Complex對象,即:Complex Linshi = 9;
    2、c1 = linshi;
    */
    
    std::cout << c1.real << "," << c1.imag << std::endl;

    return 0;
}

4、析構(gòu)函數(shù)

4.1、什么是析構(gòu)函數(shù)

C++面向?qū)ο蟪绦蛟O(shè)計-北京大學-郭煒【課程筆記(三)】,C++,c++,筆記,開發(fā)語言
實例:

class String{
	private :
		char * p;
	public:
		String () {
		p = new char[10];   //動態(tài)分配的內(nèi)存空間,需要釋放,在析構(gòu)函數(shù)中釋放。
		}
~ String ();
};
String ::~ String() {
delete [] p;
}

4.2、析構(gòu)函數(shù)和數(shù)組

對象數(shù)組生命結(jié)束時,對象數(shù)組的每個元素的析構(gòu)函數(shù)都會被調(diào)用。

#include<iostream>

class Ctest
{
    public:
    ~Ctest()  
    {
        std::cout << "destructor called" << std::endl;
    }
};

int main ()
{
    Ctest array[2];
    std::cout << "End Main" << std::endl;

    return 0;
}
// OUT
End Main
destructor called
destructor called

4.3、析構(gòu)函數(shù)和運算符 delete

delete 運算導致析構(gòu)函數(shù)調(diào)用
若new一個對象數(shù)組,那么用delete釋放時應(yīng)該寫 []。否則只delete一個對象(調(diào)用一次析構(gòu)函數(shù))

Ctest * pTest;
pTest = new Ctest; //構(gòu)造函數(shù)調(diào)用
delete pTest; //析構(gòu)函數(shù)調(diào)用
------------------------------------------------------------------
pTest = new Ctest[3]; //構(gòu)造函數(shù)調(diào)用3次
delete [] pTest; //析構(gòu)函數(shù)調(diào)用3次

析構(gòu)函數(shù)在對象作為函數(shù)返回值返回后被調(diào)用

/*
日期:2024.02.17
作者:源仔
*/

#include<iostream>

class CMyclass
{
    public:
    ~CMyclass() {std::cout << "destructor" << std::endl;}
};

CMyclass obj;   // 全局對象
CMyclass fun(CMyclass sobj)  
{
    return sobj;
    /*
    1、參數(shù)對象消亡也會導致析構(gòu)函數(shù)被調(diào)用。
    2、函數(shù)調(diào)用返回時,生成臨時對象返回
    */
}

int main()
{
    obj = fun(obj);   // 函數(shù)調(diào)用的返回值(臨時對象)被
    return 0;         // 用過后,該臨時對象析構(gòu)函數(shù)被調(diào)用
}

// OUT
destructor  //指的是CMyclass fun(CMyclass sobj)中的CMyclass sobj形參使用結(jié)束,調(diào)用析構(gòu)函數(shù)
destructor  //指的是fun(obj)臨時變量使用結(jié)束,調(diào)用析構(gòu)函數(shù)
destructor  //指的是CMyclass obj;全局對象消完,調(diào)用析構(gòu)函數(shù)

5、構(gòu)造函數(shù)析構(gòu)函數(shù)調(diào)用時機

#include<iostream>
class Demo
{
	int id;
	public:
		Demo(int i)
		{
			id = i;
			std::cout << "id = " << id << " constructor " << std::endl;
		}
		~Demo()
		{
			std::cout << "id = " << " destructed " << std::endl;
		}
};

Demo d1(1);   // 1、全局對象,在main函數(shù)之前就初始化了,就會引發(fā)構(gòu)造函數(shù),輸出:id = 1 constructor
void Func()
{
    static Demo d2(2);  // 靜態(tài)的局部變量,整個程序結(jié)束,靜態(tài)變量才會消完
    Demo d3(3);
    std::cout << "func" << std::endl;
}

int main()
{
    Demo d4(4);  // 2、輸出:id = 4 constructor
    d4 = 6;      // 3、調(diào)用類型轉(zhuǎn)換構(gòu)造函數(shù),構(gòu)建為6的臨時構(gòu)造函數(shù),輸出:id = 6 constructor,臨時構(gòu)造函數(shù)調(diào)用完就會直接銷毀,引發(fā)析構(gòu)函數(shù)調(diào)用,輸出:id = destructed
    std::cout << "main" << std::endl;  // 輸出:main
    {
        Demo d5(5);   // 4、局部對象,輸出:id = 5 constructor
    }  // 5、局部變量銷毀,引發(fā)析構(gòu)函數(shù)調(diào)用。輸出:id = destructed
    Func();  // 6、如下
    /*
    6、輸出:id = 2 constructor
    7、輸出:id = 3 constructor
    8、輸出:Func
    9、靜態(tài)的局部變量,整個程序結(jié)束,靜態(tài)變量才會消完,所以不會先引發(fā) static Demo d2(2)的析構(gòu)函數(shù)
    10、先引發(fā)Demo d3(3);的析構(gòu)函數(shù),輸出:id = destructed
    */
    std::cout << "main ends" << std::endl;  // 11、輸出:main ends

    /*
    12、引發(fā)d4 = 6;中d4的析構(gòu)函數(shù)調(diào)用(注意:之前引發(fā)的析構(gòu)函數(shù)是 6 創(chuàng)建臨時構(gòu)造函數(shù)引發(fā)的析構(gòu)函數(shù)調(diào)用),輸出:id = destructed
    13、引發(fā)static Demo d2(2);的析構(gòu)函數(shù)調(diào)用,輸出:id = destructed
    14、引發(fā)Demo d4(4);的析構(gòu)函數(shù)調(diào)用,輸出:id = destructed
    */
    return 0;
}

/*
id = 1 constructor 
id = 4 constructor 
id = 6 constructor 
id =  destructed 
main
id = 5 constructor 
id =  destructed 
id = 2 constructor 
id = 3 constructor 
func
id =  destructed 
main ends
id =  destructed 
id =  destructed 
id =  destructed 
*/

實例5:

假設(shè)A是一個類的名字,下面的程序片段會類A的調(diào)用析構(gòu)函數(shù)幾次?
答案:調(diào)用3次。
解釋:new創(chuàng)建的動態(tài)變量,必須要釋放,才能引發(fā)析構(gòu)函數(shù)的調(diào)用。文章來源地址http://www.zghlxwxcb.cn/news/detail-825993.html

int main()
{
	A * p = new A[2];
	A * p2 = new A;
	A a;
	delete [] p;
}

到了這里,關(guān)于C++面向?qū)ο蟪绦蛟O(shè)計-北京大學-郭煒【課程筆記(三)】的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包