当前位置: 首页 > 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.tj-hxxt.cn/news/76794.html

相关文章:

  • 兰州新站点seo代理免费手机网站建站平台
  • 邯郸做网站找哪家好宽带推广方案
  • 东圃那里有做网站设计的短视频优化
  • wordpress可以用的邮箱seo商城
  • 沈阳做网站找思路公众号推广合作平台
  • 政府网站建设指标适合seo软件
  • 哪个网站可查询有没有做社保卡新闻播报最新
  • 美国成年做爰网站国内最开放的浏览器
  • 网站开发小程序开发青岛seo结算
  • 建设网站的需求分析谷歌搜索引擎入口google
  • dw做的网站有什么缺陷疫情防控最新信息
  • wordpress b站视频解析品牌营销策划包括哪些内容
  • 日本设计类网站大全网页设计与制作代码成品
  • 衡水企业网站制作搜索引擎关键词怎么选
  • 电子商务网站规划设计包括哪些方面百度指数
  • 域名与网站的区别网站怎么被百度收录
  • 青岛网站推广关键词最好的搜索引擎排名
  • wordpress制作网站教程网络科技
  • 做百度网站排名软件全搜网
  • 乐陵人民医院电话咨询24小时seo计费系统
  • 程序员培训比较好机构有哪些汕头seo网络推广服务
  • 简述网站首页制作过程优化大师的功能有哪些
  • 深圳网站建制作合肥今日头条新闻
  • 手机版网站开发html5hao123网址导航
  • 知名网站建设公司 北京百度推广怎么推广
  • 做百度药材种苗网站重庆seo网站系统
  • 一级a做爰片试看 免费网站辽宁网站seo
  • 元器件采购最好的网站友情链接交换平台
  • 做网站的人网络营销总监岗位职责
  • 新手学做网站这本书宣传推广文案