前言:作为一个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是等价的。 如果不对的地方,欢迎大家来打。。,不对,是来告诉我,别让我陷入其中,不可自拔 好啦,女神经要睡觉了。。。。。。。。。。。。。。。 |