标签:style blog http color 使用 os io strong
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函数,友元
标签:style blog http color 使用 os io strong
原文地址:http://blog.csdn.net/tototuzuoquan/article/details/38738525