IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 《C++99个常见错误》读后感2 -> 正文阅读

[C++知识库]《C++99个常见错误》读后感2

第七章 多态问题

//  在面向对象思想中,对象的型别由其行为决定,而非由其状态决定
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(); }
  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-02 16:34:44  更:2021-12-02 16:35:35 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 9:29:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码