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功能,朋友