1. 拷貝構(gòu)造
// 拷貝構(gòu)造的規(guī)則 , 有兩種方式實(shí)現(xiàn)初始化。
//1 、一個(gè)是通過(guò)在后面 :a(x),b(y) 的方式實(shí)現(xiàn)初始化。
//2 、另外一種初始化的方式是直接在構(gòu)造方法里面實(shí)現(xiàn)初始化。
案比例如以下:
#include<iostream> //假設(shè)聲明已經(jīng)定義。邊不會(huì)生成 class classA { private: int a; int b; public: //拷貝構(gòu)造的規(guī)則,有兩種方式實(shí)現(xiàn)初始化 //1、一個(gè)是通過(guò)在后面:a(x),b(y)的方式實(shí)現(xiàn)初始化 //2、另外一種初始化的方式是直接在構(gòu)造方法里面實(shí)現(xiàn)初始化 classA(int x,int y)//:a(x),b(y) { a = x; b = y; } void print() { std::cout << a << " " << b << std::endl; } }; void main() { classA class1(10,100);//編譯器會(huì)默認(rèn)生成默認(rèn)的構(gòu)造函數(shù) classA class2(class1);//編譯器會(huì)生成默認(rèn)的拷貝構(gòu)造函數(shù) class1.print(); //默認(rèn)的拷貝構(gòu)造函數(shù),說(shuō)明能夠通過(guò)類的方式實(shí)現(xiàn)淺拷貝 class2.print(); std::cin.get(); }
2. 深度拷貝。使用深度拷貝的時(shí)候要將分配內(nèi)存。這是當(dāng)中的關(guān)鍵點(diǎn)。
#define _CRT_SECURE_NO_WARNINGS #include <iostream> #include<string> class string { public: char *p; int length; string(int num, char *str) { //獲取長(zhǎng)度,分配內(nèi)存。拷貝內(nèi)容 length = num; p = new char[length]; //深度拷貝的時(shí)候,要分配內(nèi)存 memset(p, 0, length);// strcpy(p, str); } string(const string & string1) { this->p = new char[string1.length]; this->length = string1.length; //將開(kāi)辟的內(nèi)存中的內(nèi)容賦值為0 memset(this->p, 0, this->length); strcpy(this->p, string1.p); } ~string() { delete[] p;//刪除的時(shí)候要帶上[] } }; void main() { string *pstr1 = new string(10, "hello"); std::cout << pstr1->p << std::endl; string *pstr2 = new string(*pstr1); delete pstr1; std::cout << pstr2->p << std::endl; std::cin.get(); }
上面的執(zhí)行結(jié)果是:
void main() { string str1(10,"hello"); std::cout << str1.p << std::endl; string str2(str1); //這里說(shuō)明能夠通過(guò) std::cout << str2.p << std::endl; std::cin.get(); }
執(zhí)行結(jié)果例如以下:
3. 關(guān)于 delete 和 default 相關(guān)的操作
A:delete 能夠禁用默認(rèn)生成的函數(shù)。禁用構(gòu)造能夠無(wú)法實(shí)例化,禁用拷貝構(gòu)造,能夠?qū)崿F(xiàn)禁止別人拷貝你。
B:default 的作用是讓函數(shù)默認(rèn)存在。
myclassA::myclassA(void); //嘗試引用已刪除的函數(shù) myclassA() = delete; //默認(rèn)刪除構(gòu)造函數(shù)。無(wú)法實(shí)例化 myclassA(const myclassA &) = delete; //拷貝構(gòu)造函數(shù) myclassA(const myclassA &) = default; ~myclassA(); void main() { //myclassA myclassa1; //myclassA myclassa2(myclassa1); //myclassA myclassa3 = myclassa1; //重載了=,依據(jù)類型 //myclassA a1; }
4.explicit.cpp
#include <iostream> #include <array> class classobj { public: int num; public: //使用有參構(gòu)造,使用explicit explicit classobj(int data) { this->num = data; std::cout << "被構(gòu)造" << num << std::endl; } ~classobj() { std::cout << "被銷(xiāo)毀" << num << std::endl; } protected: private: }; void main() { //C 語(yǔ)言風(fēng)格的數(shù)組,構(gòu)造一個(gè)數(shù)組,銷(xiāo)毀一個(gè)數(shù)組 classobj obj(0);//單獨(dú)獨(dú)有構(gòu)造函數(shù) //C語(yǔ)言風(fēng)格數(shù)組構(gòu)造方式 classobj objx[3] = { classobj(1), classobj(2), classobj(3) }; classobj (*ppobjA)[3] = &objx; //指向數(shù)組的指針 classobj *pobj(new classobj(4)); classobj * ppobj[3];//數(shù)組。每個(gè)元素都是指針 ppobj[0] = new classobj(5); ppobj[1] = new classobj(6); ppobj[2] = new classobj(7); std::cin.get(); }
執(zhí)行結(jié)果例如以下:
?
5. 類的賦初值
第一種方式 : ? 在構(gòu)造函數(shù)后面通過(guò)加上 ? : 變量名 ( 變量值 )
另外一種方式:在構(gòu)造函數(shù),函數(shù)體里面寫(xiě)上 ?? 變量名 = 變量值 ;
第三種方式:類名 對(duì)象名 = 變量值
#include <iostream> #include <array> class classobj { public: int num; public: //使用有參構(gòu)造,使用explicit classobj(int data) { this->num = data; std::cout << "被構(gòu)造" << num << std::endl; } ~classobj() { std::cout << "被銷(xiāo)毀" << num << std::endl; } protected: private: }; void main() { classobj num = 5;//賦值號(hào),類型轉(zhuǎn)換 num = 6; //說(shuō)明類的初始化能夠通過(guò)等號(hào)的方式賦值 classobj data(7); classobj obj(8); //創(chuàng)建對(duì)象必須合適的構(gòu)造函數(shù) //C++風(fēng)格數(shù)組的作用 classobj *p = new classobj(9); std::array<classobj, 2> myarray = { obj, *p }; std::cin.get(); }
執(zhí)行結(jié)果是:
賦值案例 2 :
#include <iostream> class myclass { public: int num; public: myclass():num(4)//初始化第一種方式 { //num = 10; //另外一種方式 } myclass(int data) //構(gòu)造函數(shù)能夠重載 { std::cout << "class create by data: " << data << std::endl; num = data; } ~myclass() { std::cout << "class delete"; } }; void run() { myclass myclass1(10); myclass myclass2 = 102; myclass *p = new myclass(103); myclass *p2(new myclass(104)); std::cout << (*p).num << std::endl; //std::cout << myclass1.num << std::endl; }; void main() { run(); std::cin.get(); }
執(zhí)行結(jié)果例如以下:
6. 構(gòu)造函數(shù)與析構(gòu)函數(shù)
A :系統(tǒng)自己主動(dòng)生成了構(gòu)造函數(shù)與析構(gòu)函數(shù)
B :被包括的,最先調(diào)用構(gòu)造。最后調(diào)用析構(gòu)
C :包括別人的,最后調(diào)用構(gòu)造,最先調(diào)用析構(gòu)
案例說(shuō)明:
#include <iostream> //系統(tǒng)自己主動(dòng)給你生成了構(gòu)造函數(shù)與析構(gòu)函數(shù) //被包括的。最先分配,最后釋放(這里是調(diào)用析構(gòu)不是釋放內(nèi)存) //包括別人的,最后分配,最先釋放(這里是調(diào)用析構(gòu)不是釋放內(nèi)存) class fushu { public: fushu(); ~fushu(); }; fushu::fushu() { std::cout << "fushu構(gòu)建" << std::endl; } fushu::~fushu() { std::cout << "fushu銷(xiāo)毀" << std::endl; } class math { public: fushu fushu1;//一個(gè)類調(diào)用另外一個(gè)類 math() { std::cout << "math構(gòu)建" << std::endl; } ~math() { std::cout << "math銷(xiāo)毀" << std::endl; } }; void go() { math math1; } void main() { go(); std::cin.get(); }
執(zhí)行結(jié)果截圖:
分析,上面的 math 類調(diào)用 fushu 這個(gè)類,這個(gè)結(jié)果說(shuō)明了 A,B,C.
7. 成員函數(shù)和內(nèi)聯(lián)函數(shù)
A: 內(nèi)聯(lián)函數(shù)一般在頭文件里。
編寫(xiě)頭文件:
#pragma once #include <iostream> class fushu { public: int x; int y; public: fushu(); ~fushu(); void show(); //顯示內(nèi)聯(lián) inline void showall(int x, int y); //編譯器優(yōu)化,默認(rèn)隱式內(nèi)聯(lián) void setxy(int x, int y); void show(int x,int y); }; //內(nèi)聯(lián)函數(shù)原則上放在頭文件,而且在實(shí)現(xiàn)內(nèi)聯(lián)函數(shù)的時(shí)候。去掉inline標(biāo)識(shí)符 //內(nèi)聯(lián)函數(shù)須要展開(kāi),(VS2013是要求放在頭文件的) void fushu::showall(int x, int y) { std::cout << "頭文件里內(nèi)聯(lián)函數(shù)showall:this->x = " <<(this->x = x) << "this->y =" <<(this->y = y) << std::endl; }
頭文件里的實(shí)現(xiàn)類
#include "fushu.h" //::這個(gè)符號(hào)卡面必須是類或者命名空間 fushu::fushu() { std::cout << "對(duì)象被創(chuàng)建" << std::endl; } fushu::~fushu() { std::cout << "對(duì)象被銷(xiāo)毀" << std::endl; } //類調(diào)用成員函數(shù)。須要明白那個(gè)類的對(duì)象調(diào)用 void fushu::show() { std::cout << "show" << std::endl; } void fushu::setxy(int x, int y)//編譯器優(yōu)化,默認(rèn)隱式內(nèi)聯(lián) { this->x = x; this->y = y; std::cout << "實(shí)現(xiàn)類中setxy:(this->x)= "<<(this->x)<< " (this->y)=" << (this->y) << std::endl; } void fushu::show(int x, int y) { std::cout << "實(shí)現(xiàn)類中show:(this->x)= " << (this->x) << " (this->y)=" << (this->y) << std::endl; }
調(diào)用函數(shù):
#include<iostream> #include "fushu.h" void stackrun() { fushu fushu1;//對(duì)象在棧上 fushu1.show(); } void heaprun() { fushu *pfushu = new fushu;//對(duì)象在堆上 pfushu->show(); pfushu->showall(10, 9); pfushu->setxy(19, 29); pfushu->show(1, 2); //內(nèi)部成員函數(shù)重載,函數(shù)指針。明白了參數(shù) delete pfushu; } void main() { heaprun(); std::cin.get(); }
7. 關(guān)于內(nèi)存
#include <iostream> class myclass { public: int num; int data; int *p; const int coint;//常量必須在構(gòu)造函數(shù)中初始化 int & myint; //引用必須初始化,在構(gòu)造函數(shù)中初始化 static int shu; //聲明。在外部進(jìn)行初始化 static const int dashu; public: static void go(){} void run(){} //常量,引用。必須重載構(gòu)造函數(shù)初始化 myclass(int a, int b) :myint(a), coint(b) { //引用就是共用地址,常量新開(kāi)辟備份機(jī)制 std::cout << &a << " " << &b << std::endl; std::cout << &myint << " " << &coint << std::endl; const int *p = &coint;//地址 std::cout << *p << " " << coint << std::endl; int *px = const_cast<int *>(p);//去掉const轉(zhuǎn)換 *px = 12; std::cout << coint << " " << *px << std::endl; } ~myclass(){} }; //對(duì)于靜態(tài)的變量要在類外面初始化 int myclass::shu = 0; //對(duì)于靜態(tài)的變量要在類外面初始化 const int myclass::dashu = 20; void main() { const int *px = &(myclass::dashu); std::cout << px << std::endl; int *p = const_cast<int *>(px); //靜態(tài)常量區(qū)能夠訪問(wèn)。不能夠改動(dòng),所以以下的方式是錯(cuò)誤的 //*p = 123; std::cout << *px << " " << *p << " " << myclass::dashu; std::cin.get(); }
執(zhí)行結(jié)果是:
8. 關(guān)于默認(rèn)參數(shù)
#include<iostream> class goodclass { public: int num = 1;//默認(rèn)初始化的值,C++11特定 const int data = 90;//const,這樣的方式初始化就不須要寫(xiě)構(gòu)造函數(shù)了 public: static void show(goodclass good1) { std::cout << good1.num << " " << good1.data << std::endl; } }; //類中的const默認(rèn)還是能夠改動(dòng),與C語(yǔ)言const一致 void main() { goodclass good1; goodclass::show(good1); const int *px = &(good1.data); //這里表示指向常量的值 std::cout << px << std::endl; int *p = const_cast<int *> (px);//取消常量屬性 *p = 123; std::cout << *px << " " << *p << " " << good1.data << std::endl; goodclass::show(good1); std::cin.get(); }
執(zhí)行結(jié)果:
9. 在類里面定義一個(gè)靜態(tài)變量。實(shí)現(xiàn)計(jì)數(shù)并限制 QT 中彈出窗口,建立 QMainWindow 的 QT 項(xiàng)目。
(假設(shè)想讓 QT 支持 C++11 的語(yǔ)法,須要在 QT 項(xiàng)目的 pro 文件里增加: CONFIG += c++11 ,能夠再最后面附加上)當(dāng)中 main.cpp 的代碼是:
#include "mainwindow.h" #include <QApplication> #include <QDebug> //這個(gè)頭文件要加上 class mywindow { public: mainwindow *p; //這里的mainwidow標(biāo)識(shí)的是窗口類 static int num; //全部類都能夠訪問(wèn)靜態(tài)區(qū) mywindow() { if(num > 2)//靜態(tài)類成員進(jìn)行成員 {} else { num++; qDebug()<<"create"; this->p = new mainwindow;//實(shí)例化一個(gè)對(duì)象 this->p->show();//讓這個(gè)窗口顯示 } } ~mywindow() { qDebug() << "delete"; delete this->p; } }; //對(duì)靜態(tài)變量賦初值 int mywindow::num = 0; void run() { mywindow my1;//棧上 } int main(int argc, char *argv[]) { QApplication a(argc, argv); mywindow *pwindow = new mywindow; qDebug() << mywindow::num;//通過(guò)這行打印出次數(shù) //以下是低嗎快 { mywindow *pwindow=new mywindow; qDebug() << pwindow->num; } { mywindow *pwindow=new mywindow; qDebug() << pwindow->num; } { mywindow *pwindow=new mywindow; qDebug() << pwindow->num; } return a.exec(); }
10. 靜態(tài)函數(shù)和普通函數(shù)
#include "mainwindow.h" #include <QApplication> #include <stdlib.h> #include <QDebug> class mywindow { public: MainWindow w; public: static void run() //由于加了static。所以不用實(shí)例化就能夠用。 { system("calc"); } void notepad() { system("notepad"); } }; class mywindowW { public: MainWindow w; //繼承 int # public: mywindowW(int data):num(data) //給data初始化 {} }; int main(int argc, char *argv[]) { QApplication a(argc, argv); mywindow mywindow1; mywindow1.w.show(); mywindow1.run(); //第一種調(diào)用方式 mywindow1.notepad(); //mywindow1::notepad();//這樣的方式不能夠直接地調(diào)用 mywindow::run();//不須要實(shí)例化的情況就能夠調(diào)用 return a.exec(); }
執(zhí)行結(jié)果是彈出計(jì)算器和記事本。
11. 函數(shù)默認(rèn)參數(shù),對(duì)于給含有默認(rèn)參數(shù)的函數(shù)賦值的時(shí)候,參數(shù)的賦值將從左往右賦值給函數(shù)中的參數(shù)。
案比例如以下:
#include "mainwindow.h" #include <QApplication> class mywindow { public: MainWindow w; MainWindow *p; //假設(shè)在調(diào)用的時(shí)候僅僅傳遞一個(gè)參數(shù)的時(shí)候,這個(gè)參數(shù)賦值給了str1 void settitle(char *str1="XYZ",char *str2="THG") { w.setWindowTitle(str1); p->setWindowTitle(str2); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); mywindow my1; my1.p=new MainWindow; my1.w.show(); my1.p->show(); //傳遞參數(shù)的時(shí)候,從左往右填充。比方以下的AHNJ將賦值給*str1 //能夠僅僅傳遞一個(gè)參數(shù),也能夠傳遞兩個(gè)參數(shù) my1.settitle("AHNJ"); return a.exec(); }
執(zhí)行結(jié)果例如以下:
12. 加了 const 之后函數(shù)和沒(méi)有加 const 變量的函數(shù)的差別:
新建 QT 項(xiàng)目,編寫(xiě)代碼:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT //以下是新加入的 public: int x; int y; mutable int z;//不受const成員函數(shù)的約束 public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); void resetxy();//沒(méi)有const屬性,能夠改動(dòng)成員變量 void showxy() const; //const,不能夠改動(dòng)一般的成員變量 private: Ui::MainWindow *ui; }; #endif // MAINWINDOW_H 編寫(xiě)MainWindow的實(shí)現(xiàn) #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); } MainWindow::~MainWindow() { delete ui; } void MainWindow::resetxy() { this->x = 800; this->y = 600; resize(this->x,this->y); } void MainWindow::showxy() const { //由于是加了const,所以不再能夠調(diào)用成員變量 //this->x = 10; //由于沒(méi)有加上mutable。所以不能夠調(diào)用 //this->y = 100; this->z = 1000; } 調(diào)用main函數(shù) #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; //重置窗體大小 w.resetxy(); w.show(); return a.exec(); }
13. 關(guān)于友元函數(shù)。案比例如以下(不用改動(dòng) QT 的頭文件和頭文件的實(shí)現(xiàn)類):
#include "mainwindow.h" #include <QApplication> //友元函數(shù)能夠訪問(wèn)類中的私有變量。還能夠訪問(wèn)私有函數(shù) //友元函數(shù)聲明的時(shí)候要有friend,定義的時(shí)候不須要friend了 //定義友元的時(shí)候也能夠在內(nèi)的內(nèi)部 class mywindow { MainWindow *p; void go() { system("notepad"); } //聲明一個(gè)友元函數(shù) void friend showwindow(mywindow * pwin); }; //實(shí)現(xiàn)一個(gè)友元函數(shù) void showwindow(mywindow *pwin) { pwin->p=new MainWindow; pwin->p->show(); pwin->go(); } int main(int argc, char *argv[]) { QApplication a(argc, argv); mywindow my1; // my1.p; showwindow(&my1); return a.exec(); }
14. 友元類,當(dāng)指向了一個(gè)指針的時(shí)候一定要初始化。
否則將出現(xiàn)錯(cuò)誤。以下的函數(shù)任然是 main.cpp 中的內(nèi)容。
#include "mainwindow.h" #include <QApplication> //被友元 class window { MainWindow *p; void settitle() { this->p->setWindowTitle("1234"); } friend class opwindow;//友元類 }; class opwindow { private: window pwin; //類的變量,指針能夠訪問(wèn)類的全部私有成員與函數(shù) window *ppwin;//指針必須初始化,必須分配內(nèi)存 public: void init() { //不初始化就是野指針,所以這里一定要初始化,不然會(huì)報(bào)錯(cuò) ppwin = new window; ppwin->p = new MainWindow(); ppwin->p->show(); } void setstr() { ppwin->settitle(); } }; int main(int argc, char *argv[]) { QApplication a(argc, argv); opwindow opwindow1; opwindow1.init(); opwindow1.setstr();//語(yǔ)法 return a.exec(); }
友元類案例 2
頭文件 QT 項(xiàng)目:
#ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); //重載 MainWindow(const MainWindow & w) { MainWindow(0); } ~MainWindow(); private: Ui::MainWindow *ui; //友元類 friend class window; }; #endif // MAINWINDOW_H main.cpp #include "mainwindow.h" #include <QApplication> class window { public: MainWindow w; MainWindow *p; }; int main(int argc, char *argv[]) { QApplication a(argc, argv); window window1; window1.w.show(); window1.p = new MainWindow(window1.w); window1.p->show(); return a.exec(); }
?
?
版權(quán)聲明:本文博客原創(chuàng)文章。博客,未經(jīng)同意,不得轉(zhuǎn)載。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
