| 前言:作为一个C++的新手,希望可以通过自己的努力,变得更好! 刚接触到句柄,对句柄的理解很浅显;就是减少重复编译而产生的;如果我们改动了某个头文件,那么所有包含这个头文件的相关文件都得进行重新编译、连接等等等,这在大项目中,是非常耗费时间的; 使用句柄类(头文件和接口都不变,有一个指向结构的指针),只改动实现的部分,我们可以对句柄实现的方法进行修改,但保持头文件和公共的接口不改变,这也就是可以减少不必要的编译时间; 句柄要如何使用呢?接下来我将根据自己的理解写一小段代码。 实验一: #ifndef NSJHANDLE_H
#define NSJHANDLE_H
#include <iostream>
using namespace std;
class NSJHandle
{
public:
    NSJHandle();
    struct  Handle1;  
    Handle1 *pNsjHandle;
    void init();   
    void read();
    void setData();
};
#endif 
 #include "nsjhandle.h"
#include <stdlib.h>
#include<QDebug>
NSJHandle::NSJHandle()
{
   init();
}
struct NSJHandle::Handle1{  
public:
    void setData(int tmpData1);  
    int  getData();
private:
    int      data1;
    double   data2;
};
void NSJHandle::init()  
{
    pNsjHandle = (Handle1*)malloc(sizeof(Handle1));
}
void NSJHandle::read() 
{
    if(pNsjHandle) cout<<"data1:"<<pNsjHandle->getData()<<endl;
}
void NSJHandle::setData() 
{
    if(pNsjHandle) pNsjHandle->setData(10);
}
void NSJHandle::Handle1::setData(int tmpData1)
{
    data1 = tmpData1;
}
int NSJHandle::Handle1::getData()
{
    return data1;
}
 #ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "nsjhandle.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
    void test();
private:
    Ui::MainWindow *ui;
    NSJHandle pDemoHandle; 
};
 #include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <iostream>
std::string num;
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    pDemoHandle.setData(); 
    pDemoHandle.read();
}
MainWindow::~MainWindow()
{
    delete ui;
}
 
 实验二: 偶然看见别人封住好留出来的接口,突然想说,能不能自己也模拟出他们预留出来的接口。先上代码: 先定义一个抽象类:这是我们暴露出来给别人的公共接口
 #ifndef NSJHANDLE_H
#define NSJHANDLE_H
#include <iostream>
using namespace std;
class NSJHandle
{
public:
    virtual  void  read() = 0;
    virtual  void  setData() = 0;
};
extern "C"{
   NSJHandle *creatorHandleType(int type); 
}
#endif 
 #ifndef NSJINHERITHANDLE_H
#define NSJINHERITHANDLE_H
#include"nsjhandle.h"
using namespace std;
class NSJInheritHandle : public NSJHandle   
{
public:
    NSJInheritHandle();
    ~NSJInheritHandle();
    struct  Handle1;
    Handle1 *pHandle;
    void  init();
    void  read();
    void  setData() ;
};
#endif 
 #include "nsjinherithandle.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <QDebug>
NSJInheritHandle::NSJInheritHandle()
{
}
NSJInheritHandle::~NSJInheritHandle()
{
    if(pHandle){
        delete pHandle;
        pHandle = nullptr;
    }
}
struct NSJInheritHandle::Handle1{
public:
    void setData(int tmpData1);
    int  getData();
private:
    int      data1;
    double   data2;
};
void NSJInheritHandle::init()
{
    pHandle = (Handle1*)malloc(sizeof(Handle1));
}
void NSJInheritHandle::read()
{
    if(pHandle) cout<<"data1:"<<pHandle->getData()<<endl;
}
void NSJInheritHandle::setData()
{
    if(pHandle) pHandle->setData(10);
}
void NSJInheritHandle::Handle1::setData(int tmpData1)
{
    data1 = tmpData1;
}
int NSJInheritHandle::Handle1::getData()
{
    return data1;
}
NSJHandle *creatorHandleType(int type){  
    if(0 == type){
       NSJInheritHandle *inheritHandle = new NSJInheritHandle;
       inheritHandle->init();
       return inheritHandle;
    }
}
 #include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <iostream>
#include "nsjinherithandle.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
  NSJHandle * handle = creatorHandleType(0); 
  handle->setData();
  handle->read();
}
MainWindow::~MainWindow()
{
    delete ui;
}
 这样,结果跟之前的是一致的。 总结在这个代码的编写过程中,有两个C++的基础是需要我们知道的1)什么是虚函数?什么是纯虚函数?有什么需要注意的地方?2)new和malloc直接的区别是什么,在C++中如果使用不当会造成什么样的问题?
         首先,根据我编写的过程出现的错误,来一步步的查找和理解这些问题; 1)什么是虚函数?什么是纯虚函数?有什么需要注意的地方? 
          (1) 虚函数:简单的理解就是被virtual修饰的成员函数,是为了实现多态性而产生的;目的很简单,就是为了接口与具体实现的分离,使用同名函数,但因对象个体不同而指向相对应的函数;             class A{
   virtual void fun();
}
class B : public A{
   void fun();
} 
class C : public A{
   void fun();
} 
            (2)纯虚函数:就是在类声明的时候定义一个函数声明,但不被定义实现,是留着给继承它的派生类实现的,派生类一定的定义基类中的纯虚函数,不然该对象不能被实例化;纯虚函数的书写很简单,就是在虚函数的基础上,在函数体后面加上 “= 0”这个后缀,用来标记其是纯虚函数; class A{
   virtual void fun() = 0; 
}
class B : public A{
   void fun();
} 
class C : public A{   
 
} 
           (1)new和malloc最大的差距就在于:malloc是直接在堆上分配一段内存,而new出了分配内存外,它还会调用类的构造函数;这就是他们之间最大的区别。 | new的功能 | 创建了一个对象,分配内存 | 调用构造函数 |  | malloc的功能 | 分配内存 |  |  | delete的功能 | 删除了一个对象,释放内存 | 调用析构函数 |  | free的功能 | 释放内存 |  | 
     | new \ delete | new是保留字,不需要加载头文件;new delete 是运算符; |  | malloc \ free | malloc是需要头文件支持的; malloc,free是函数 | 
    注意点:我们不要企图用malloc/free来完成动态对象的内存管理,应该用new/delete。由于内部数据类型的“对象”没有构造与析构的过程,对它们而言malloc/free和new/delete是等价的。 如果不对的地方,欢迎大家来打。。,不对,是来告诉我,别让我陷入其中,不可自拔 好啦,女神经要睡觉了。。。。。。。。。。。。。。。 |