zoukankan      html  css  js  c++  java
  • 拷贝构造函数,深拷贝,大约delete和default相关业务,explicit,给定初始类,构造函数和析构函数,成员函数和内联函数,关于记忆储存,默认参数,静态功能和正常功能,const功能,朋友

    

    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.关于deletedefault相关的操作

    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中弹出窗口,建立QMainWindowQT项目。

    (假设想让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();
    }
    

     

     

    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    沙尘天气,但还是要坚持锻炼
    为了欧冠,堕落两天
    NRF24L01测试板子完成了
    昨天参加ti的研讨会了
    自我安慰一下
    功率W与dBm的对照表及关系
    短时间提高英语口语方法
    看了一个星期的欧洲杯,熬阿
    最近比较忙,项目较累
    后台获取js赋给服务器控件的值
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4668534.html
Copyright © 2011-2022 走看看