·考虑提供更搞效且安全的swap函数:
对于一般缺省的swap函数,可能引发拷贝构造函数,导致性能下降,swap应设计为提供异常安全性保障而不抛出异常,但缺省版本的swap时可能抛出的,所以重新设计swap是应该的。此前设计 operator= 函数也有稍微提过。此外考虑类的设计模式,也会有低效率的swap函数,如pimpl:
在 Widget.h 头文件下:
class WidgetImpl{}; //前向声明,用于做Widget类的成员指针
class Widget{
Widget();
~Widget();
void interface() //公共接口
private:
WidgetImpl *ptr_WidgetImpl
};
在 Widget.cpp 实现文件下:
class WidgetImpl{
...//Widget类功能
priavte:
...//widget类的资源
};
假设需要为Widget准备一个swap函数,直接调用缺省swap函数相当于:
void swap(Widget &lhs,Wdiget &rhs){
Widget temp(lhs); //引发了拷贝构造,拉低效率
lhs = rhs; //拷贝构造函数是运行抛出异常的
rhs = tmp;
}
比较优化的实现方式是:
//1: 提供public swap member成员函数,让其高校的置换两个对象值:
class Widget{
public:
void swap(Widget &other){
using std::swap;
swap(pImp,other.pImpl); //一一对资源交换
}
...
};
namespace std{
template<> //对std::swap版本的进行特化
void swap<Widget>(Widget& a,Widget& b){
a.swap(b); //调用成员swap
}
}
//2: 在Widget 或 template 所在的命名空间提供一个non-member //swap,并令其调用上述swap成员函数:
namspace Widgetstuff{
... //模板化WidgetImpl
template<typename T>
class Widget{...}; //模板Widget包含swap成员函数
template<typename T>
void swap(Widget<T>&a, //有时设计类时non-member 版本
Widget<T>&b){ //比menber 版本更要好,所以
a.swap(b) //比较推荐不容易使类设计变大的
} //做法
};
//3: 正在编写一个非模板类时,为std::swap以你的类进行特化,并令其调//用你的swap函数,点1示例。
//[注意]:在编写函数模板时,应该在内部调用前 using std::swap,保
//证swap在有无特化版本下都能够选对模板。
template<typename T>
void fun(T& a,T& b){
using std::swap;
sawp(a,b);
}
·将文件间的编译依存关系降至最低
一个成熟的程序其内部的类结构是极其复杂的,互相包含引用,错综复杂。对于过于耦合的类设计,文件间的编译依存关系是很严重的,为此我们通常要进行解耦,降低文件间的编译依存关系。一个庞大的类,类部肯定包含相当多的其他类类型,每当对内部的类结构做更改时,其内存结构也会做很多更改。特别是,当我们声明一个类变量的时候,编译器会根据类结构开辟内存空间,并且涉及构造函数的调用。内存资源很快就会被占用上去。为此,我们有两种设计类的方式:Handle class 和 Interface class 两种方式,来延迟编译器对类结构的分析,减少一开始对类文件的依赖。这两种方法都基于运用指针。
Handle class: 实质是pImpl,用类管理类。
在myclass头文件中:
#ifndef MYCLASS_H
#define MYCLASS_H
//#include "xxx1.h" //原myclass所需要的资源可以不需要了
//#include "xxx2.h" //原myclass所需要的资源
class xxx1;
class xxx2; //用类声明替换
//将原本的其他成员变量被一个realmyclass类或结构体包裹代替
class realmyclass; //以类类型为例
class myclass{
public:
myclass(...); //构造函数,所有成员函数不做实现
~myclass(...); //只做声明
func1();
func2();
....
private:
std::shard_ptr<realmyclass>ptr;//推荐使用智能指针管理
};
#endif
在myclass类实现文件中:
#include "myclass.h"
#include xxx1 //提供资源头文件
#include xxx2
class realmyclass{
private:
xxx1 parm1; //原来在myclass的成员资源移动到此
xxx2 parm2;
...
public:
realmyclass(...) //提供相同的构造函数构造函数
func1(){...};
func2(){...}; //于myclass同名的成员函数
...
};
//myclass的构造函数调用myclass的实现类指针
myclass::myclass(...){
this->ptr = std::shared_ptr<realmyclass>(...)
}
//myclass 的成员函数靠指针调用实现类中的函数
myclass::func1(){this->ptr->func1;}
myclass::func2(){this->ptr->func2;}
//完成类的实现,视情况添加,此处shared_ptr可不做要求
myclass::~myclass() = default;
Interface Handle:通过继承的方式,子类做实现,让父类成为接口提供子类方法的调用。有点像工厂设计模式。
myclass类头文件:
#ifndef MYCLASS_H
#define MYCLASS_H
class xxx1;
class xxx2;
class myclass{
public:
virtual ~myclass() = default;
virtual func1() const = 0; //声明为纯虚函数
virtual func2() const = 0;
//通过返回一个静态对象,同样先不做实现
static std::shard_ptr<myclass> create(...);
};
//有需要的可以将构造函数添加delete关键字或者声明为private,防止不期望下调用构造函数获取对象。
#endif
derived_myclass类头文件:
#ifndef DERIVED_MYCLASS_H
#define DERIVED_MYCLASS_H
#include "myclass.h" //包含父类头文件
#include xxx1; //包含资源头文件
#include xxx2;
class derived_myclass : public myclass{
public:
derived_myclass(...):... //构造函数,通过列表参数初始化
func1() const override{...}//重写虚函数,实现方法
func2() const override{...}
private:
xxx1 parm1; //原先myclass的成员资源移动过到此
xxx2 parm2;
};
#endif
derived_myclass类实现文件:
//不要忘了实现父类中的静态类成员方法,记住父类指针可以接收子类对象
static std::shard_ptr<myclass> myclass::create(...){
return std::shared<myclass>(
new derived_myclass(...));
}
标签:std,...,Widget,Effective,c++,class,swap,myclass,day
From: https://www.cnblogs.com/XuefengMing/p/17880801.html