第七章 多态问题
// 在面向对象思想中,对象的型别由其行为决定,而非由其状态决定
class Base {
public:
enum Tcode { DER1, DER2, DER3 };
Base( Tcode c ) : code_( c ) {}
virtual ~Base();
int tcode() const
{ return code_; }
virtual void f() = 0;
private:
Tcode code_;
};
class Der1 : public Base {
public:
Der1() : Base( DER1 ) {}
void f();
};
// 用多态。
class Base {
public:
enum Tcode { DER1, DER2, DER3 };
Base();
virtual ~Base();
virtual int tcode() const = 0;
virtual void f() = 0;
};
class Der1 : public Base {
public:
Der1() : Base() {}
void f();
int tcode() const
{ return DER1; }
};
// 这是单态设计模式的一个实例。
class MsgType {
public:
virtual ~MsgType() {}
virtual int code() const = 0;
virtual Msg *generate( RawMsgSource & ) const = 0;
};
class Firewall { // 单态设计模式
public:
void addMsgType( const MsgType * );
Msg *genMsg( RawMsgSource & );
private:
typedef std::vector<MsgType *> C;
typedef C::iterator I;
static C types_;
};
Msg *Firewall::genMsg( RawMsgSource &src ) {
int code = src.msgcode;
for( I i( types_.begin() ); i != types_.end(); ++i )
if( code == i->code() )
return i->generate( src );
return 0;
}
void Firewall::addMsgType( const MsgType *mt )
{ types_.push_back(mt); }
class Msg1Type : public MsgType {
public:
Msg1Type()
{ Firewall::addMsgType( this ); }
int code() const
{ return MSG1; }
Msg *generate( RawMsgSource &src ) const
{ return new Msg1( src ); }
};
// user
Firewall::instance().addMessageType( mt );
Firewall fw;
fw.genMsg( rawsource );
FireWall().genMsg( rawsource ); // 虽然通过不同的 class 对象,但状态同一
// 重载虚函数会造成多义性
void update( int );
void update( double );
// 改成
class Thing {
public:
// ...
void update( int );
void update( double );
protected:
virtual void updateInt( int );
virtual void updateDouble( double );
};
inline void Thing::update( int a )
{ updateInt( a ); }
inline void Thing::update( double d )
{ updateDouble( d ); }
// 避免在虚函数中提供引数默认初始化物
// 头文件 thing.h
const int minim = 12;
namespace SCI {
class Thing {
// ...
virtual void doitNtimes( int numTimes = minim ); // 意为::minim
};
}
// 头文件 mything.h
namespace SCI {
const int minim = 10;
class MyThing : public Thing {
// ...
void doitNtimes( int numTimes = minim ); // 意为 SCI::minim: 10没用生效
};
}
class Thing {
// ...
void doitNtimes( int numTimes = minim )
{ doitNtimesImpl( numTimes ); }
protected:
virtual void doitNtimesImpl( int numTimes );
};
// 不要在在构造函数和析构函数中调用虚函数
第八章 型别设计问题
class C {
public:
C();
// ...
private:
int a_;
const int b_;
int &ra_; // 存在指针或者引用,必须自行撰写复制构造函数”:避免使用常量和引用数据成员
};
// 同时禁止
private:
int a_;
int b_;
int *pa_;
C( const C & ); // 禁止复制构造
C &operator =( const C & ); // 禁止(复制)赋值
// 适当的解决方案是将数据成员 len_的声明加上 mutable 饰词
size_t BoundedString::length() const {
if( len_ < 0 )
const_cast<int &>(len_) = strlen( buf_ ); // mutable int len_;
return len_;
}
void setRole( Role *newRole ); // 不知道是否持有,需要删除
void adoptRole( Role *newRole ); // 取得拥有权
void shareRole( const Role *sharedRole ); // 无拥有权
void copyRole( const Role *roleToCopy ); // 取得副本的拥有权
// 仍然不明确
PtrList<Employee> management;
Manager theBoss;
management.append( &theBoss );
// 避免拥有权问题沟通无效的最佳做法就是采用标准库中的容器组件
std::list<Employee *> management;
Manager theBoss;
management.push_back( &theBoss ); // 没问题
Iter &operator ++(); // 前置式, 前置式总是优于后置式
Iter operator ++(int); // 后置式,会有一个匿名对象的产生,还有析构。
++i; // 等价于 i.operator ++();
i++; // 等价于 i.operator ++(0);
++i = j; // 没问题
i++ = j; // 合法,但实际上应该标为错误!
// 但该地址不属于 i,而属于一个编译器
// 生成的匿名临时 class 对象,而且在指针被初始化之后该对象旋即被析构
const Iter *ip = &i++; // error
// 复制操作永不经由模板成员函数完成
template <Currency currency>
Money<currency> &
Money<currency>::operator =( const Money<currency> &that ) {
myCurve_ = that.myCurve_;
// Curve 对象中发生了内存泄漏、别名问题和意外修改等灾难!
amt_ = myCurve_->
convert( currency, otherCurrency, rhs.get_amount() );
}
第九章 继承谱系设计问题
// 当心持有 class 对象的数组,尤其是持有基类对象的数组
void apply( B array[], int length, void (*f)( B & ) ) {
for( int i = 0; i < length; ++i )
f( array[i] );
}
// ...
D *dp = new D[3]; // 赋值发生地址偏移
// 彻底舍弃裸数组,而使用某种标准库中的容器组件,一般选用 vector组件。
vector<B *> vbp; // 可以进行多态应用
// 尝试以传递(指涉到) Bond 型别(的指针)作为(指涉到) Inst 型别(的指针)的实际
// 引数来解决此问题是毫无助益的
bool Equity::compare( Inst *ip ) const {
int bunits = ip->units(); // 错误!
return units() < bunits;
}
// 将其在继承谱系中
// 的位置提升,这样它的存在不会给既有的派生类型别带来更大的耦合
bool Inst::unitCompare( const Inst *ip ) const
{ return units() < ip->units(); }
// 友元
class Bond : public Inst {
public:
friend bool compare( const Equity *, const Bond * );
// ...
};
class Equity : public Inst {
public:
friend bool compare( const Equity *, const Bond * );
// ...
};
bool compare( const Equity *eq, const Bond *bond )
{ return eq->units() < bond->units(); }
|