1. 拷貝構造
// 拷貝構造的規則 , 有兩種方式實現初始化。
//1 、一個是通過在后面 :a(x),b(y) 的方式實現初始化。
//2 、另外一種初始化的方式是直接在構造方法里面實現初始化。
案比例如以下:
#include<iostream>
//假設聲明已經定義。邊不會生成
class classA
{
private:
int a;
int b;
public:
//拷貝構造的規則,有兩種方式實現初始化
//1、一個是通過在后面:a(x),b(y)的方式實現初始化
//2、另外一種初始化的方式是直接在構造方法里面實現初始化
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);//編譯器會默認生成默認的構造函數
classA class2(class1);//編譯器會生成默認的拷貝構造函數
class1.print();
//默認的拷貝構造函數,說明能夠通過類的方式實現淺拷貝
class2.print();
std::cin.get();
}
2. 深度拷貝。使用深度拷貝的時候要將分配內存。這是當中的關鍵點。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include<string>
class string
{
public:
char *p;
int length;
string(int num, char *str)
{
//獲取長度,分配內存。拷貝內容
length = num;
p = new char[length]; //深度拷貝的時候,要分配內存
memset(p, 0, length);//
strcpy(p, str);
}
string(const string & string1)
{
this->p = new char[string1.length];
this->length = string1.length;
//將開辟的內存中的內容賦值為0
memset(this->p, 0, this->length);
strcpy(this->p, string1.p);
}
~string()
{
delete[] p;//刪除的時候要帶上[]
}
};
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();
}
上面的執行結果是:
void main()
{
string str1(10,"hello");
std::cout << str1.p << std::endl;
string str2(str1); //這里說明能夠通過
std::cout << str2.p << std::endl;
std::cin.get();
}
執行結果例如以下:
3. 關于 delete 和 default 相關的操作
A:delete 能夠禁用默認生成的函數。禁用構造能夠無法實例化,禁用拷貝構造,能夠實現禁止別人拷貝你。
B:default 的作用是讓函數默認存在。
myclassA::myclassA(void); //嘗試引用已刪除的函數
myclassA() = delete; //默認刪除構造函數。無法實例化
myclassA(const myclassA &) = delete; //拷貝構造函數
myclassA(const myclassA &) = default;
~myclassA();
void main()
{
//myclassA myclassa1;
//myclassA myclassa2(myclassa1);
//myclassA myclassa3 = myclassa1; //重載了=,依據類型
//myclassA a1;
}
4.explicit.cpp
#include <iostream>
#include <array>
class classobj
{
public:
int num;
public:
//使用有參構造,使用explicit
explicit classobj(int data)
{
this->num = data;
std::cout << "被構造" << num << std::endl;
}
~classobj()
{
std::cout << "被銷毀" << num << std::endl;
}
protected:
private:
};
void main()
{
//C 語言風格的數組,構造一個數組,銷毀一個數組
classobj obj(0);//單獨獨有構造函數
//C語言風格數組構造方式
classobj objx[3] = { classobj(1), classobj(2), classobj(3) };
classobj (*ppobjA)[3] = &objx; //指向數組的指針
classobj *pobj(new classobj(4));
classobj * ppobj[3];//數組。每個元素都是指針
ppobj[0] = new classobj(5);
ppobj[1] = new classobj(6);
ppobj[2] = new classobj(7);
std::cin.get();
}
執行結果例如以下:
?
5. 類的賦初值
第一種方式 : ? 在構造函數后面通過加上 ? : 變量名 ( 變量值 )
另外一種方式:在構造函數,函數體里面寫上 ?? 變量名 = 變量值 ;
第三種方式:類名 對象名 = 變量值
#include <iostream>
#include <array>
class classobj
{
public:
int num;
public:
//使用有參構造,使用explicit
classobj(int data)
{
this->num = data;
std::cout << "被構造" << num << std::endl;
}
~classobj()
{
std::cout << "被銷毀" << num << std::endl;
}
protected:
private:
};
void main()
{
classobj num = 5;//賦值號,類型轉換
num = 6; //說明類的初始化能夠通過等號的方式賦值
classobj data(7);
classobj obj(8); //創建對象必須合適的構造函數
//C++風格數組的作用
classobj *p = new classobj(9);
std::array<classobj, 2> myarray = { obj, *p };
std::cin.get();
}
執行結果是:
賦值案例 2 :
#include <iostream>
class myclass
{
public:
int num;
public:
myclass():num(4)//初始化第一種方式
{
//num = 10; //另外一種方式
}
myclass(int data) //構造函數能夠重載
{
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();
}
執行結果例如以下:
6. 構造函數與析構函數
A :系統自己主動生成了構造函數與析構函數
B :被包括的,最先調用構造。最后調用析構
C :包括別人的,最后調用構造,最先調用析構
案例說明:
#include <iostream>
//系統自己主動給你生成了構造函數與析構函數
//被包括的。最先分配,最后釋放(這里是調用析構不是釋放內存)
//包括別人的,最后分配,最先釋放(這里是調用析構不是釋放內存)
class fushu
{
public:
fushu();
~fushu();
};
fushu::fushu()
{
std::cout << "fushu構建" << std::endl;
}
fushu::~fushu()
{
std::cout << "fushu銷毀" << std::endl;
}
class math
{
public:
fushu fushu1;//一個類調用另外一個類
math()
{
std::cout << "math構建" << std::endl;
}
~math()
{
std::cout << "math銷毀" << std::endl;
}
};
void go()
{
math math1;
}
void main()
{
go();
std::cin.get();
}
執行結果截圖:
分析,上面的 math 類調用 fushu 這個類,這個結果說明了 A,B,C.
7. 成員函數和內聯函數
A: 內聯函數一般在頭文件里。
編寫頭文件:
#pragma once
#include <iostream>
class fushu
{
public:
int x;
int y;
public:
fushu();
~fushu();
void show();
//顯示內聯
inline void showall(int x, int y);
//編譯器優化,默認隱式內聯
void setxy(int x, int y);
void show(int x,int y);
};
//內聯函數原則上放在頭文件,而且在實現內聯函數的時候。去掉inline標識符
//內聯函數須要展開,(VS2013是要求放在頭文件的)
void fushu::showall(int x, int y)
{
std::cout << "頭文件里內聯函數showall:this->x = "
<<(this->x = x) << "this->y =" <<(this->y = y) << std::endl;
}
頭文件里的實現類
#include "fushu.h"
//::這個符號卡面必須是類或者命名空間
fushu::fushu()
{
std::cout << "對象被創建" << std::endl;
}
fushu::~fushu()
{
std::cout << "對象被銷毀" << std::endl;
}
//類調用成員函數。須要明白那個類的對象調用
void fushu::show()
{
std::cout << "show" << std::endl;
}
void fushu::setxy(int x, int y)//編譯器優化,默認隱式內聯
{
this->x = x;
this->y = y;
std::cout << "實現類中setxy:(this->x)= "<<(this->x)<< " (this->y)=" << (this->y) << std::endl;
}
void fushu::show(int x, int y)
{
std::cout << "實現類中show:(this->x)= " << (this->x) << " (this->y)=" << (this->y) << std::endl;
}
調用函數:
#include<iostream>
#include "fushu.h"
void stackrun()
{
fushu fushu1;//對象在棧上
fushu1.show();
}
void heaprun()
{
fushu *pfushu = new fushu;//對象在堆上
pfushu->show();
pfushu->showall(10, 9);
pfushu->setxy(19, 29);
pfushu->show(1, 2);
//內部成員函數重載,函數指針。明白了參數
delete pfushu;
}
void main()
{
heaprun();
std::cin.get();
}
7. 關于內存
#include <iostream>
class myclass
{
public:
int num;
int data;
int *p;
const int coint;//常量必須在構造函數中初始化
int & myint; //引用必須初始化,在構造函數中初始化
static int shu; //聲明。在外部進行初始化
static const int dashu;
public:
static void go(){}
void run(){}
//常量,引用。必須重載構造函數初始化
myclass(int a, int b) :myint(a), coint(b)
{
//引用就是共用地址,常量新開辟備份機制
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轉換
*px = 12;
std::cout << coint << " " << *px << std::endl;
}
~myclass(){}
};
//對于靜態的變量要在類外面初始化
int myclass::shu = 0;
//對于靜態的變量要在類外面初始化
const int myclass::dashu = 20;
void main()
{
const int *px = &(myclass::dashu);
std::cout << px << std::endl;
int *p = const_cast<int *>(px);
//靜態常量區能夠訪問。不能夠改動,所以以下的方式是錯誤的
//*p = 123;
std::cout << *px << " " << *p << " " << myclass::dashu;
std::cin.get();
}
執行結果是:
8. 關于默認參數
#include<iostream>
class goodclass
{
public:
int num = 1;//默認初始化的值,C++11特定
const int data = 90;//const,這樣的方式初始化就不須要寫構造函數了
public:
static void show(goodclass good1)
{
std::cout << good1.num << " " << good1.data << std::endl;
}
};
//類中的const默認還是能夠改動,與C語言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();
}
執行結果:
9. 在類里面定義一個靜態變量。實現計數并限制 QT 中彈出窗口,建立 QMainWindow 的 QT 項目。
(假設想讓 QT 支持 C++11 的語法,須要在 QT 項目的 pro 文件里增加: CONFIG += c++11 ,能夠再最后面附加上)當中 main.cpp 的代碼是:
#include "mainwindow.h"
#include <QApplication>
#include <QDebug> //這個頭文件要加上
class mywindow
{
public:
mainwindow *p; //這里的mainwidow標識的是窗口類
static int num; //全部類都能夠訪問靜態區
mywindow()
{
if(num > 2)//靜態類成員進行成員
{}
else
{
num++;
qDebug()<<"create";
this->p = new mainwindow;//實例化一個對象
this->p->show();//讓這個窗口顯示
}
}
~mywindow()
{
qDebug() << "delete";
delete this->p;
}
};
//對靜態變量賦初值
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;//通過這行打印出次數
//以下是低嗎快
{
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. 靜態函數和普通函數
#include "mainwindow.h"
#include <QApplication>
#include <stdlib.h>
#include <QDebug>
class mywindow
{
public:
MainWindow w;
public:
static void run() //由于加了static。所以不用實例化就能夠用。
{
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(); //第一種調用方式
mywindow1.notepad();
//mywindow1::notepad();//這樣的方式不能夠直接地調用
mywindow::run();//不須要實例化的情況就能夠調用
return a.exec();
}
執行結果是彈出計算器和記事本。
11. 函數默認參數,對于給含有默認參數的函數賦值的時候,參數的賦值將從左往右賦值給函數中的參數。
案比例如以下:
#include "mainwindow.h"
#include <QApplication>
class mywindow
{
public:
MainWindow w;
MainWindow *p;
//假設在調用的時候僅僅傳遞一個參數的時候,這個參數賦值給了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();
//傳遞參數的時候,從左往右填充。比方以下的AHNJ將賦值給*str1
//能夠僅僅傳遞一個參數,也能夠傳遞兩個參數
my1.settitle("AHNJ");
return a.exec();
}
執行結果例如以下:
12. 加了 const 之后函數和沒有加 const 變量的函數的差別:
新建 QT 項目,編寫代碼:
#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成員函數的約束
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void resetxy();//沒有const屬性,能夠改動成員變量
void showxy() const; //const,不能夠改動一般的成員變量
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
編寫MainWindow的實現
#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,所以不再能夠調用成員變量
//this->x = 10;
//由于沒有加上mutable。所以不能夠調用
//this->y = 100;
this->z = 1000;
}
調用main函數
#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. 關于友元函數。案比例如以下(不用改動 QT 的頭文件和頭文件的實現類):
#include "mainwindow.h"
#include <QApplication>
//友元函數能夠訪問類中的私有變量。還能夠訪問私有函數
//友元函數聲明的時候要有friend,定義的時候不須要friend了
//定義友元的時候也能夠在內的內部
class mywindow
{
MainWindow *p;
void go()
{
system("notepad");
}
//聲明一個友元函數
void friend showwindow(mywindow * pwin);
};
//實現一個友元函數
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. 友元類,當指向了一個指針的時候一定要初始化。
否則將出現錯誤。以下的函數任然是 main.cpp 中的內容。
#include "mainwindow.h"
#include <QApplication>
//被友元
class window
{
MainWindow *p;
void settitle()
{
this->p->setWindowTitle("1234");
}
friend class opwindow;//友元類
};
class opwindow
{
private:
window pwin; //類的變量,指針能夠訪問類的全部私有成員與函數
window *ppwin;//指針必須初始化,必須分配內存
public:
void init()
{
//不初始化就是野指針,所以這里一定要初始化,不然會報錯
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();//語法
return a.exec();
}
友元類案例 2
頭文件 QT 項目:
#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();
}
?
?
版權聲明:本文博客原創文章。博客,未經同意,不得轉載。
拷貝構造函數,深拷貝,大約delete和default相關業務,explicit,給定初始類,構造函數和析構函數,成員函數和內聯函數,關于記憶儲存,默認參數,靜態功能和正常功能,const功能,朋友
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

