-
有的情况下,现在的折衷方案比未来的理想方案好得多
-
我考虑问题的本质是什么,再定义一个类抓住这个本质,并确保这个类能独立地工作。然后在遇到符合这个本质的问题时就使用这个类。
-
只要类定义正确,我就只能按照我编写它的初衷那样去用它。
-
C++ 哲学:抽象,实用,只为用到的东西付出代价。
-
类设计者的核查表:
- 你的类需要一个构造函数吗?
- 你的数据成员是私有的吗?(使用函数,可以延迟计算,不必时时计算,保证数据成员的准确性)
- 你的类需要一个无参的构造函数吗?(对象数组)
- 是不是每个构造函数初始化所有的数据成员?
- 类需要析构函数吗?
- 类需要一个虚析构函数吗?
- 你的类需要复制构造函数吗?(是否需要深拷贝)
- 你的类需要一个赋值操作符吗?
- 你的赋值操作符能正确地将对象赋给对象本身吗?
- 你的类需要定义关系操作符吗?
- 删除数组时你记住了用 delete[] 吗?
- 记得在复制构造函数和赋值操作符的参数类型中加上 const 了吗?
- 如果函数有引用参数,它们应该是 const 引用吗?
- 记得适当地声明成员函数为 const 的了吗?
-
代理类:用类来表示概念(RAII)
class Vehicle{ public: virtual double weight() = 0; virtual void start() = 0; virtual Vehicle* copy() const = 0; virtual ~Vehicle(){} }; class RoadVehicle: public Vehicle{ /* ... */ }; class AutoVehicle: public RoadVehicle{ /* ... */ }; class Aircraft: public Vehicle{ /* ... */ }; class Helicopter: public Aircraft{ /* ... */ }; // 定义代理类 class VehicleSurrogate{ public: VehicleSurrogate(){ // 空代理 vp(0); } VehicleSurrogate(const Vehicle& v){ vp = v.copy(); } ~VehicleSurrogate(){ delete vp; } VehicleSurrogate(const VehicleSurrogate& v){ vp(v.vp ? v.vp->copy() : 0); } VehicleSurrogate& operator=(const VehicleSurrogate&){ if(this != &v){ delete vp; vp = (v.vp ? v.vp->copy() : 0); } return *this; } /* 其实代理类也可以不依依写出 Vehicle 所能支持的其他操作 只需要实现 * 和 -> 的操作符重载即可,做一次转发, 但这样就过多地暴露了内存分配方面的策略,不太安全 */ double weight() const{ if(vp == 0){ throw "empty VehicleSurrogate.weight()"; } return vp->weight(); } void start() { if(vp == 0){ throw "empty VehicleSurrogate.start()"; } return vp->start(); } private: Vehicle* vp; }; int main(){ // Vehicle parking_lot[1000]; // wrong VehicleSurrogate parking_lot[1000]; // OK AutoVehicle x; parking_lot[num_vehicles++] = x; return 0; }
-
Handle 句柄类:就是一种只包含单个对象的容器 与智能指针的理念类似,智能指针更像是 Handle 类的抽象
class Point{ public: Point(int x = 0, int y = 0):xval(x), yval(y){ cout << "Point()" << endl; } Point(const Point& p){ cout << "Point(const Point& p)" << endl; xval = p.xval; yval = p.yval; } ~Point(){ cout << "~Point()" << endl; } int x() const {return xval;} int y() const {return yval;} Point& x(int xv){ xval = xv; return *this; } Point& y(int yv){ yval = yv; return *this; } void print(){ cout << "x: " << xval << " y: " << yval << endl; } private: int xval, yval; }; class Handle; class UPoint{ friend class Handle; Point p; int u; UPoint():u(1){} UPoint(int x, int y):p(x, y), u(1){} UPoint(const Point& p0):p(p0), u(1){} }; class Handle{ public: Handle():up(new UPoint){} Handle(int x, int y):up(new UPoint(x, y)){} Handle(const Point &p):up(new UPoint(p)){} Handle(const Handle &h):up(h.up){++up->u;} ~Handle(){ if(--up->u == 0){ delete up; } } Handle& operator=(const Handle& h){ ++h.up->u; if(--up->u == 0){ delete up; } up = h.up; cout << up->u << endl; return *this; } int x() const{ return up->p.x(); } int y() const{ return up->p.y(); } /*指针语义 不必复制 UPoint 对象 Handle& x(int x){ up->p.x(x); return *this; } Handle& y(int y){ up->p.y(y); return *this; } */ /*值语义 写时复制 */ Handle& x(int x){ copyWhenWrite(); up->p.x(x); return *this; } Handle& y(int y){ copyWhenWrite(); up->p.y(y); return *this; } private: void copyWhenWrite(){ if(up->u != 1){ --up->u; up = new UPoint(up->p); } } private: UPoint * up; }; int main() { Point p(10, 20); Handle hp(p); // 通过拷贝构造创建一个p的副本,并将 handle绑定到该副本 Handle hpp(hp); Handle hppp(hp); Handle hpppp; hpppp = hp; hpppp.x(100).y(200); cout << hp.x() << ", " << hp.y() << endl; cout << hpppp.x() << ", " << hpppp.y() << endl; return 0; }
输出:
Point() Point(const Point& p) 1 2 3 Point() ~Point() 4 Point(const Point& p) 10, 20 100, 200 ~Point() ~Point() ~Point()
-
对象和值之间的差别只在要改变对象时才显现出来。换句话说,就是值和不可变的对象是无法区分的。