当前位置: 首页 > news >正文

大兴安岭网站制作做网页多少钱一个页面

大兴安岭网站制作,做网页多少钱一个页面,网页链接调用服务是干嘛的,如何注册一个网站域名备案写在前面 Pimpl(Pointer to implementation,又称作“编译防火墙”) 是一种减少代码依赖和编译时间的C编程技巧,其基本思想是将一个外部可见类(visible class)的实现细节(一般是所有私有的非虚成员)放在一个单独的实现类(implemen…

写在前面

Pimpl(Pointer to implementation,又称作“编译防火墙”) 是一种减少代码依赖和编译时间的C++编程技巧,其基本思想是将一个外部可见类(visible class)的实现细节(一般是所有私有的非虚成员)放在一个单独的实现类(implementation class)中,而在可见类中通过一个私有指针来间接访问该实现类。

下面通过一个简单示例说明为什么使用Pimpl、如何使用Pimpl。

类普通实现

这里创建一个简单的Fruit类,实现如下:

//Fruit.h
#pragma once
#include <string>class Fruit
{
public:Fruit();~Fruit();void display();void setPrice(double dbPrice);double getPrice() const;private:std::string m_sName;double m_dbPrice;
};
//Fruit.cpp
#include "Fruit.h"
#include <iostream>Fruit::Fruit() : m_sName(""), m_dbPrice(0.0)
{std::cout << "Fruit::Fruit\n";
}Fruit::~Fruit()
{std::cout << "Fruit::~Fruit\n";
}void Fruit::display()
{std::cout << "Name: " << m_sName << ", Price: " << m_dbPrice << std::endl;
}void Fruit::setPrice(double dbPrice)
{std::cout << "ruit::setPrice: " << dbPrice << std::endl;m_dbPrice = dbPrice;
}double Fruit::getPrice() const
{std::cout << "Fruit::getPrice\n";return m_dbPrice;
}

在其他文件(例main函数)中引用类:

//main.cpp
#include <iostream>
#include "Fruit.h"int main()
{Fruit fruit;fruit.setPrice(5.88);fruit.display();
}

上面是常见的类定义及使用方式,这里可以很明显的发现两个问题:
①头文件暴露了私有成员。当然对于内部开发这无关紧要,但对于一些对外的模块开发(如dll),外部使用人员有可能通过对外的头文件中的私有成员,推测内部实现,这显然不是公司所乐意见到的。
②接口和实现耦合,存在严重编译依赖性。例上面示例只实现的price成员的对外接口,若添加name成员的对外接口(setName、getName), 所有引用Fruit.h头文件的源文件(Fruit.cpp, main.cpp)都需要重新编译,在大型的项目中,这会花费很多编译时间。

因此,对于需要对外隐藏信息或想要减少编译依赖的需求,可以Pimpl模式实现类。

Pimpl实现

在上面Fruit类的基础上调整:

//Fruit.h
#pragma once
//事先声明
class FruitPrivate;
class Fruit
{
public:Fruit();~Fruit();void display();void setPrice(double dbPrice);double getPrice() const;//为避免后续对头文件进行修改,可事先预留所有成员的对外接口void setName(const std::string& sName);std::string getName() const;private://成员放至私有类//std::string m_sName;//double m_dbPrice;FruitPrivate* m_priFruit;};
//Fruit.cpp
#include "Fruit.h"
#include <iostream>
#include <string>/***********************************FruitPrivate*********************************************/
class FruitPrivate
{
public:FruitPrivate();~FruitPrivate();void display();void setPrice(double dbPrice);double getPrice() const;private:std::string m_sName;double m_dbPrice;};FruitPrivate::FruitPrivate() : m_sName(""), m_dbPrice(0.0)
{std::cout << "FruitPrivate::FruitPrivate\n";
}FruitPrivate::~FruitPrivate()
{std::cout << "PruitPrivate::~FruitPrivate\n";
}void FruitPrivate::display()
{std::cout << "FruitPrivate::display--Name: " << m_sName << ", Price: " << m_dbPrice << std::endl;
}void FruitPrivate::setPrice(double dbPrice)
{std::cout << "FruitPrivate::setPrice--price: " << dbPrice << std::endl;
}double FruitPrivate::getPrice() const
{std::cout << "FruitPrivate::getPrice";return m_dbPrice;
}/***********************************end FruitPrivate*********************************************/Fruit::Fruit() : m_priFruit(new FruitPrivate)//m_sName(""), m_dbPrice(0.0)
{std::cout << "Fruit::Fruit\n";
}Fruit::~Fruit()
{std::cout << "Fruit::~Fruit\n";if (m_priFruit != nullptr){delete m_priFruit;}
}void Fruit::display()
{//std::cout << "Name: " << m_sName << ", Price: " << m_dbPrice << std::endl;m_priFruit->display();
}void Fruit::setPrice(double dbPrice)
{//std::cout << "ruit::setPrice: " << dbPrice << std::endl;//m_dbPrice = dbPrice;m_priFruit->setPrice(dbPrice);
}double Fruit::getPrice() const
{//std::cout << "Fruit::getPrice\n";//return m_dbPrice;return m_priFruit->getPrice();
}//按需实现
void Fruit::setName(const std::string& sName)
{}std::string Fruit::getName() const
{}

在其他文件(上例main函数)中的引用不变。

可以看到上面调整后的头文件中不再对外展示私有成员,取而代之的是私有类的指针,原本的私有成员存放到私有类中,以实现隐藏。

另外,再添加name成员的对外接口(头文件已预留),只需重新编译Fruit.cpp即可,极大程度地减少编译依赖。

优点

信息隐藏。私有成员完全可以隐藏在共有接口之外,尤其对于闭源API的设计尤其的适合。同时,很多代码会应用平台依赖相关的宏控制,这些琐碎的东西也完全可以隐藏在实现类当中,给用户一个简洁明了的使用接口。
加速编译。这通常是用pImpl手法的最重要的收益,称之为编译防火墙(compilation firewall),主要是阻断了类的接口和类的实现两者的编译依赖性。这样,类用户不需要额外include不必要的头文件,同时实现类的成员可以随意变更,而公有类的使用者不需要重新编译。
二进制兼容性。通常对一个类的修改,会影响到类的大小、对象的表示和布局等信息,那么任何该类的用户都需要重新编译才行。而且即使更新的是外部不可访问的private部分,虽然从访问性来说此时只有类成员和友元能否访问类的私有部分,但是私有部分的修改也会影响到类使用者的行为,这也迫使类的使用者需要重新编译。

而对于使用pImpl手法,如果实现变更被限制在实现类中,那公有类只持有一个实现类的指针,所以实现做出重大变更的情况下,pImpl也能够保证良好的二进制兼容性,这是pImpl的精髓所在。

缺点

在私有类中对公有类的访问需另外设计实现。相较于常规实现,这显然会加大开发人员的时间成本,不过在Qt中,有提供Q指针和D指针,以支持公有类和私有类的相互访问,而无需另外实现。
Pimpl对拷贝操作比较敏感,要么禁止拷贝操作,要么就需要自定义拷贝操作。每个类都需要对自己的所有成员的拷贝、赋值等操作负责。在公有类中虽然只有一个私有类的指针成员,但其(私有类)内部有多少成员,在外人看来不得而知,因此共有类和私有类都需担负起成员的拷贝、赋值等操作的责任。
编译器将不再能够捕获const方法中对成员变量的修改。因为私有成员变量已经从公有类脱离到了实现类当中了,公有类的const只能保护指针值本身是否改变,而不再能进一步保护其所指向的数据。例上面对外的get接口,虽然在公有类中限制为const(不能修改私有类成员指针指向),但在调用的私有类对于接口的内部也有变动成员的可能(上例中在私用类对外的get接口后有加const限制)。

注意事项

pImpl最需要关注的就是共有类的复制语义,因为实现类是以指针的方式作为共有类的一个成员,而默认C++生成的拷贝操作只会执行对象的浅拷贝,这显然违背了pImpl的原本意图,除非是真的想要底层共享一个实现对象。针对这个问题,解决方式有:
禁止复制操作 :将所有的复制操作定义为private的,或者继承 boost::noncopyable,或者在新标准中将这些复制操作定义为delete;
显式定义复制语义:创建新的实现类对象,执行深拷贝。要么不定义拷贝、移动操作符,要定义就需要将他们全部重新定义。

优化

使用指针指针管理私有类指针成员,拷贝、赋值操作限制。

//Fruit.h
#pragma once
#include <string>
#include <memory>class FruitPrivate;class Fruit
{
public:Fruit();~Fruit();//拷贝、赋值操作处理Fruit(const Fruit&) = delete;				//私有成员为指针,禁止浅拷贝Fruit& operator=(const Fruit&) = delete;	//禁止赋值操作//可实现移动拷贝Fruit(Fruit&&) = default;Fruit& operator=(Fruit&&) = default;void display();void setPrice(double dbPrice);double getPrice() const;//为避免后续对头文件进行修改,可事先预留所有成员的对外接口void setName(const std::string& sName);std::string getName() const;private://成员放至私有类//std::string m_sName;//double m_dbPrice;//FruitPrivate* m_priFruit;//使用智能指针管理私有类指针std::unique_ptr<FruitPrivate> m_priFruit;};
//Fruit.cpp
#include "Fruit.h"
#include <iostream>/***********************************FruitPrivate*********************************************/
class FruitPrivate
{
public:FruitPrivate();~FruitPrivate();//拷贝、赋值操作和公有类保持一致FruitPrivate(const FruitPrivate&) = delete;FruitPrivate& operator=(const FruitPrivate&) = delete;FruitPrivate(FruitPrivate&&) = default;FruitPrivate& operator=(FruitPrivate&&) = default;void display();void setPrice(double dbPrice);double getPrice() const;private:std::string m_sName;double m_dbPrice;};FruitPrivate::FruitPrivate() : m_sName(""), m_dbPrice(0.0)
{std::cout << "FruitPrivate::FruitPrivate\n";
}FruitPrivate::~FruitPrivate()
{std::cout << "PruitPrivate::~FruitPrivate\n";
}void FruitPrivate::display()
{std::cout << "FruitPrivate::display--Name: " << m_sName << ", Price: " << m_dbPrice << std::endl;
}void FruitPrivate::setPrice(double dbPrice)
{std::cout << "FruitPrivate::setPrice--price: " << dbPrice << std::endl;
}double FruitPrivate::getPrice() const
{std::cout << "FruitPrivate::getPrice";return m_dbPrice;
}/***********************************end FruitPrivate*********************************************/Fruit::Fruit() : m_priFruit(std::make_unique<FruitPrivate>())//m_sName(""), m_dbPrice(0.0)
{std::cout << "Fruit::Fruit\n";
}Fruit::~Fruit()
{std::cout << "Fruit::~Fruit\n";//if (m_priFruit != nullptr)//{//	delete m_priFruit;//}
}void Fruit::display()
{//std::cout << "Name: " << m_sName << ", Price: " << m_dbPrice << std::endl;m_priFruit->display();
}void Fruit::setPrice(double dbPrice)
{//std::cout << "ruit::setPrice: " << dbPrice << std::endl;//m_dbPrice = dbPrice;m_priFruit->setPrice(dbPrice);
}double Fruit::getPrice() const
{//std::cout << "Fruit::getPrice\n";//return m_dbPrice;return m_priFruit->getPrice();
}//按需实现
void Fruit::setName(const std::string& sName)
{}std::string Fruit::getName() const
{return "";
}

总结

类的常规实现和Pimpl实现各有优劣。若只是为了快速开发且没有对外隐藏需求,常规实现无疑是很好的选择,若想要减少编译依赖且不想对外展示私有成员,可选择使用Pimpl实现,代价就是开发及维护成本的提高。

http://www.yayakq.cn/news/736094/

相关文章:

  • 网站建站思路在线设计平台行业的发展趋势
  • 网站的规划和建设弹出网站代码
  • 网站被k有什么表现全国文明网联盟网站建设
  • 网站建设需求调研过程下花园区住房和城乡建设局网站
  • 宁波专业网站定制制作服务网络建设与管理包括哪些方面
  • python做网站显示表格高新区手机网站建设
  • 网站开发提成精准营销手段
  • 常用网站建设技术是什么意思电脑做系统ppt下载网站好
  • 网站建设公司网站建设公司买链接网
  • 东莞网站模板不想网站备案如何办
  • phpcmsv9手机网站设计运动品牌网站
  • 池州网站建设网站好做吗
  • 韩国优秀网站欣赏展厅设计公司选四度科技
  • 网站建设市场行情分析定制网站和模板建站哪个好用
  • 中国查企业的网站凤岗仿做网站
  • 长沙网站建设服务网络策划方案
  • 站长之家模板138ip查询网域名解析
  • 做网站选关键词做网站推广费用
  • 制作网站需要什么做网站哪家公司比较好而且不贵
  • 怎么做公司网站seo标题制作网站
  • 旅游景点网站模板大全淘宝网站官网
  • 网站建设 焦作网站建设学什么书
  • 北京专业做网站怎么样关闭wordpress注册邮件
  • 零基础学网站建设 知乎汕头网页搜索排名提升
  • 北京微网站建设公司哪家好做恒生指数看什么网站
  • iis默认网站路径网站 制作价格表
  • 网站空间购买北京视频网站logo怎么做
  • wordpress 增加按钮企业网站优化服务主要围绕着
  • 建网站的专业公司没有网站域名是否需要备案
  • c2c网站建站的标准越南语网站怎么做