詳解C++構造函數

1.作用

一種特殊類型的方法,在每次實例化對象時運行

2.代碼舉例

2.1 示例1:

#include <iostream>
class A
{
    public:
        float a, b;
        void print()
        {
            std::cout << a <<  " ,  " << b << std :: endl;
        }
};
int main()
{
    A a;
    a.print();
    return 1;
}

運行結果:

image-20211116163007112

當我們實例化A,系統為它分配內存,我們沒有初始化內存,得到的是內存空間原有的那些東西

2.2 示例2:

當在main中添加 std::cout << a.a << ” , ” << a.b << std :: endl;

int main()
{
    A a;
    std::cout << a.a <<  " ,  " << a.b << std :: endl;
    a.print();
    return 1;
}

(ubuntu下 vs code )運行結果

image-20211116164058741

不同編譯器可能不一樣,有的會編譯不過報錯(未初始化局部變量),原因有待深入…

3. 使用

3.1 使用構造函數初始化

#include <iostream>
class A
{
    public:
        float a, b;
        A ()
        {
            a = 0.0f;
            b = 0.0f;
        }
        void print()
        {
            std::cout << a <<  " ,  " << b << std :: endl;
        }
};
int main()
{
    A a;
    std::cout << a.a <<  " ,  " << a.b << std :: endl;
    a.print();
    return 1;
}

結果:

image-20211116164932213

3.2 有參數的構造函數

#include <iostream>
class A
{
    public:
        float a, b;
    // 無參構造
    A ()
        {
            a = 0.0f;
            b = 0.0f;
        }
    // 有參構造
        A(float c,float d)
        {
            a = c;
            b = d;
        }
    
        void print()
        {
            std::cout << a <<  " ,  " << b << std :: endl;
        }
};
int main()
{
    A a(5.0,6.0);
    std::cout << a.a <<  " ,  " << a.b << std :: endl;
    a.print();
    return 1;
}

一個類可以有很多構造函數 前提是參數個數不同或者參數類型不同

類似於同名函數(函數重載 即有相同的函數名,但是有不同的參數個數與參數類型)

 A(float c,float d)
 {
 }
A(int c,int d)
{
}
A(float c,float d,float e)
{
}

這裡需要註意有參構造的時候註意傳值類型

float 類型

A a(5.0f , 6.0f);

3.3 默認的構造函數

每個類默認有一個空參空實體的構造函數(如果寫瞭構造函數,則默認構造函數就沒有瞭,需要時需手動添加)

A ()
{
}

如果不想使用構造函數有兩種方法

// 1 私有化
private :
	A(){}
// 2 刪掉
A() = delete;

4. 成員初始化列表

例1:正常初始化

#include <iostream>
using namespace std;
class Student
{
private:
    const char *m_name;
    int m_age;
    float m_score;
public:
    // 無參構造 給變量賦定值
    Student()
    {
        m_name = "aaa";
        m_age = 1;
        m_score = 99.0;
    }
    // 有參構造  給變量動態賦值
    Student(const char *name, int age, float score)
    {
        m_name = name;
        m_age = age;
        m_score = score;
    }
    void print ()
    {
        cout << m_name << " ," << m_age  <<  " ," <<  m_score << endl;
    }
};
int main(int argc, char const *argv[])
{
    Student s1;
    s1.print();
    Student s2("ccc" , 2 , 99.3f);
    s2.print();
    return 0;
}

例2:成員初始化列表

#include <iostream>
#include <string>
using namespace std;
class Student
{
private:
    // string m_name;
    // char *m_name;
    const char *m_name;
    int m_age;
    float m_score;
public:   
    //  無參 成員初始化列表  
    Student() 
        : m_name("bbb") , m_age(2) , m_score(93.0f) 
    {
        // TODO
    }
    // 有參 成員初始化列表  
    /**
     *  const char *name    常量指針     const 修飾*name   *name不可改變
     *  char * const name   指針常量     const 修飾 name   name不可改變
     *  char const *name    常量指針 等同於 const char *name 
     * 
     *  這裡不寫const 會報警告  但可以編過  
     *  
    */
    Student(const char *name, int age, float score)
        : m_name(name) , m_age(age) , m_score(score)
    {
       // TODO
    }
    void print ()
    {
        cout << m_name << " ," << m_age  <<  " ," <<  m_score << endl;
    }
};
int main(int argc, char const *argv[])
{
    Student s1;
    s1.print();
    Student s2("ccc",2,99.3f);
    s2.print();
    return 0;
}

運行結果都一樣:

aaa ,1 ,99
ccc ,2 ,99.3

使用構造函數初始化列表並沒有效率上的優勢,僅僅是書寫方便,尤其是成員變量較多時,這種寫法非常簡單明瞭。

初始化列表可以用於全部成員變量,也可以隻用於部分成員變量

Student(char *name, int age, float score): m_name(name){
    m_age = age;
    m_score = score;
}

NOTE:成員變量的初始化順序與初始化列表中列出的變量的順序無關,它隻與成員變量在類中聲明的順序有關。

為啥推薦成員初始化列表的寫法?

#include <iostream>
using namespace std;
class Example
{
public:
    Example()
    {
        cout<< "Create Example" << endl;
    }
    Example(int x)
    {
        cout<< "Create Example with "  << x << endl;
    }
};
class A
{
private:
    string m_name;
    // 創建瞭 Example 的無參構造 對象
    Example m_Example;
public:
    A()
    {
        m_name = "name";
        // 創建新的有參構造對象覆蓋第一次賦值  
        m_Example = Example(1);
    }
};
int main(int argc, char const *argv[])
{
    A a;
    return 0;
}

結果:

image-20211117113259509

A的構造函數換成成員初始化列表的寫法

//    A() : m_name ("name"),m_Example(Example(1))  		與下面寫法相同
A() : m_name ("name"),m_Example(1)
    {
    }

結果:

image-20211117113805527

總結

本篇文章就到這裡瞭,希望能夠給你帶來幫助,也希望您能夠多多關註WalkonNet的更多內容!

推薦閱讀: