文章目錄
- 1、 =default 和=delete 概述
- 2、 類與默認函數
- 3、 使用“=delete”來限制函數生成
- 4、 “=default”使用范圍
1、 =default 和=delete 概述
- =default、=delete 是C++11的新特性,分別為:顯式缺省(告知編譯器生成函數默認的缺省版本)和顯式刪除(告知編譯器不生成函數默認的缺省版本)。C++11中引進這兩種新特性的目的是為了增強對“類默認函數的控制”,從而讓程序員更加精準地去控制默認版本的函數。 其具體的功能和使用方法下面將一一道來。
2、 類與默認函數
-
在講解關鍵字 default和delete 之前,先對類和類的默認函數作下描述與說明,從而加深對這兩個關鍵字的理解與認知。既要知其然,也要知其所以然。C++中,當設計與編寫一個類時,若不顯著寫明,則類會默認提供如下幾個函數:
?????(1)構造函數
?????(2)析構函數
?????(3)拷貝構造函數
?????(4)拷貝賦值函數(operator=)
?????(5)移動構造函數?????以及全局的默認操作符函數:
?????(1)operator,
?????(2)operator &
?????(3)operator &&
?????(4)operator *
?????(5)operator->
?????(6)operator->*
?????(7)operator new
?????(8)operator delete?????注:若我們在類中實現了這些版本之后,編譯器便不會生成其對應的默認函數版本,這時需要我們顯式的寫上其對應的默認函數版本。
#include <iostream>
using namespace std;class Student{public:Student(const int a,const int b):m_a(a),m_b(b){}int getA()const {return m_a;}int getB()const {return m_b;}private:int m_a;int m_b;
};int main(int argc,char **argv){Student stu(1,2);cout << stu.getA() << endl;//1cout << stu.getB() << endl;//2Student stu1; //編譯失敗,no matching function for call to ‘Student::Student()’return 0;
}
- 編譯報錯,提示:Student.cpp: In function ‘int main(int, char**)’:Student.cpp:34:13: error: no matching function for call to ‘Student::Student()’ Student stu1;
- 例1定義了一個對象stu1,該對象將會使用Student類的無參構造函數,而該默認構造函數在Student類中,我們沒有顯式的說明。因此,c++編譯器在我們提供了該函數實現之后是不會生成與之對應的默認函數版本的。在Student中我們重載了帶2個參數的構造函數,但是無參的構造函數,沒有提供,因此會報錯。
解決辦法,在該類別中顯示的提供五參數的構造函數
#include <iostream>
using namespace std;class Student{public:Student(){} //顯示說明Student的無參構造函數Student(const int a,const int b)
// :m_a(a)
// ,m_b(b){{{m_a = a;m_b = b;}int getA()const {return m_a;}int getB()const {return m_b;}private:int m_a;int m_b;
};int main(int argc,char **argv){Student stu(1,2);cout << stu.getA() << endl;//1cout << stu.getB() << endl;//2Student stu1; //編譯失敗,no matching function for call to ‘Student::Student()’return 0;
}
學習心得
- :m_a(a),m_b(b)是一個賦值的運算
Student(const int a,const int b):m_a(a),m_b(b){{{}
等效于
Student(const int a,const int b){m_a = a;m_b = b;}
- 問題:以 Student(){} 這樣的方式來聲明無參數構造函數,會帶來一個問題,就是使得 其不再是 POD 類型,因此可能讓編譯器失去對這樣的數據類型的優化功能。這是不希望看到的。因此最好使用 = default來修飾默認構造函數。
#include<iostream>
using namespace std;
class Student
{public:Student() = default;Student(const int a,const int b):m_a(a),m_b(b){}int getA()const{return m_a;}int getB()const{return m_b;}private:int m_a;int m_b;
};int main(int argc,char **argv)
{Student stu(1,2);cout<<stu.getA()<<endl; //1cout<<stu.getB()<<endl; //2Student stu1;//使用is_pod模板類可以查看某類型是否屬于POD類型,若為POD類型,則返回1,反之,返回0std::cout<<is_pod<Student>::value<<std::endl; //1return 0;
}
3、 使用“=delete”來限制函數生成
- C++開發中,我們經常需要控制某些函數的生成。在C++11之前,經常的普遍做法是將其聲明為類的 private 成員函數,這樣若在類外這些這些函數的操作時候,編譯器便會報錯,從而達到效果。如例2:
#include<iostream>
using namespace std;
class Student
{public:Student() = default;Student(const int a,const int b):m_a(a),m_b(b){}int getA()const{return m_a;}int getB()const{return m_b;}private:Student(const Student& );Student& operator =(const Student& );private:int m_a;int m_b;
};int main(int argc,char **argv)
{Student stu(1,2);cout<<stu.getA()<<endl; //1cout<<stu.getB()<<endl; //2//Student stu1(stu);//報錯:Student.cpp:26:5: error: ‘Student::Student(const Student&)’ is private//Student stu1(3,4);//stu1 = stu;//報錯:Student.cpp:27:14: error: ‘Student& Student::operator=(const Student&)’ is privatestd::cout<<is_pod<Student>::value<<std::endl; //return 0;
}
- 例2代碼編譯報錯,因為在類中,我們將Student的拷貝構造函數和拷貝賦值函數都聲明為了 private 屬性,因此,當在類外使用拷貝構造和拷貝賦值操作值,編譯器會報錯。雖然能夠達到效果,但是不夠直觀和簡潔。對于追求高效以及簡潔來說
這樣做有2個問題:
?????(1)不是最簡化;
?????(2)對于友元支持不友好
更為簡潔直觀的方法是使用: =delete
#include<iostream>
using namespace std;
class Student
{public:Student() = default;Student(const int a,const int b):m_a(a),m_b(b){}int getA()const{return m_a;}int getB()const{return m_b;}Student(const Student& ) = delete;Student& operator =(const Student& ) = delete;private:int m_a;int m_b;
};int main(int argc,char **argv)
{Student stu(1,2);cout<<stu.getA()<<endl; //1cout<<stu.getB()<<endl; //2//Student stu1(stu);//報錯:Student.cpp:39:21: error: use of deleted function ‘Student::Student(const Student&)’//Student(const Student& );//Student stu1(3,4);//stu1 = stu;//報錯:SStudent.cpp:44:10: error: use of deleted function ‘Student& Student::operator=(const Student&)’std::cout<<is_pod<Student>::value<<std::endl; //return 0;
}
4、 “=default”使用范圍
- "=default"不僅僅局限于類的定義內,也可以用于類的定義外來修飾成員函數,如例3:
#include<iostream>
using namespace std;
class Student
{public:Student() = default;Student(const int a,const int b):m_a(a),m_b(b){}int getA()const{return m_a;}int getB()const{return m_b;}Student(const Student& ) = delete;Student& operator=(const Student& );private:int m_a;int m_b;
};Student& Student::operator =(const Student& ) = delete;int main(int argc,char **argv)
{Student stu(1,2);cout<<stu.getA()<<endl; //1cout<<stu.getB()<<endl; //2Student stu1(3,4);stu1 = stu;//編譯報錯:Student.cpp:42:10: error: use of deleted function ‘Student& Student::operator=(const Student&)’std::cout<<is_pod<Student>::value<<std::endl; //return 0;
}
- Student& Student::operator =(const Student& ) = delete;
參考鏈接
- C++11新特性之 “=default” 、“=delete”