c++设计和演化 笔记

P60: cpp的语法,太复杂了,不止cpp. 很多语言也是这样甚至更甚(对比是lisp-1).

 

P76: const 的设计引发的问题不少(比如在模板 的时候 const会让代码指数级膨胀(虽然remove_refance能修补一些)). 如果在const引入之前引入了多重继承的话 也许有更好的解决方法.

 

P83: 构造/析构 函数的命名. 用类型名做构造函数名字, 在某些(比如模板)生成代码的时候 会产生一些困惑 (pf= T::T /* ::后面应该是symbol但是是type*/) .

 

P88: 每个语句都产生一个值是好想法, 但是 if(Tok* ct= gettok()){...} 还是有些奇怪.这个和P60也有关系.

 

P95: 关于静态类型"...通过静态类型...更可能是重视地表达了一种深思熟虑 的设计".  但是问题是很多设计太大了 以至于深思熟虑是技术上不可能的.  (他自己也在P92说了"一个 好语言不是设计出来的,而是成长起来的.").  所以说这样的静态类型(或者说语法上避免动态类型)是否是最佳方案还是存疑的.

 

P130: 语言的扩充 cpp作者和委员会在扩充上遇到了一些问题 以至于采取了很保守的策略, 这也导致了cpp的进化速度太慢. 现阶段我认为还是过于保守了,如果鼓励方言(抽取共同的部分作为标准)的话应该会好一些.

 

P252: 关于构造函数和虚函数.

class box: public shape{
 point lt,rb;
public:
 point get_center(){ return (lt+rb)/2; }
 //...
};
class shape{
public:
 point center;

 shape(){
  f(); //OK
  center= get_center(); //ERROR 使用了没有初始化的虚函数
 }
 int f(){...}
 virtual point get_center()=0;
};

这样的代码是不行的, 因为box依赖于基类shape. 而shape的构造函数又依赖于子类box. 形成一个环.

c++的解决方法是在构造函数不可以调用虚函数.

但是 确实有需求怎么办,比如我就想在shape中 提供center.

只能把center从对象变成接口,然后把具体对象放在子类中:
class shape{
public:
 //...
 virtual void set_center(point)=0;
 virtual point get_center()=0;
};

这就引发了一个新问题. 在定义class的时候必须事先知道这个class是基类还是子类以决定放置对象还是接口.

这就变相的让一个子类失去了成为别人基类的能力,也就是影响了正交性.

比如,你需要给一个基本完善的对象做细微调整的时候,你想重载一个函数,但是这个函数被用在了基类的构造函数里,你就不能重载它,因为这个函数不可能被声明为virtual.

 

这时候只能用一些不怎么漂亮的办法:

class point{
 vector<float> data;
public:
 point(){}
 void init(){
  data.resize(get_D());
 }
 float operator[](size_type);
 virtual size_type get_D()=0;
};
class point3D: public point{
public:
virtual size_type get_D(){return 3;}
};
void g(point*);
void f(){
 point3D p();
 p.init();
 g(&p);
 //...
}

使用这个办法需要两个东西支持:

第一是调用的时候必须手动调用init(), 附加的,在使用别的函数的时候可能也需要检测是否init()过的成本.

第二是被初始化的东西(此例是vector<float>)必须有无参数的构造函数(或者类似的东西).否则异常退出的时候不能保证安全性.

 

二没办法解决, 一的解决可以是这样:

class point3D_warp{
 point3D data;
public:
 point3D_warp(){data.init();}
 float operator[](size_type i){ return data[i]; }
 //...
};

 

 

P254: const

const函数访问非const成员

#include<iostream>
using namespace std;

class dc{
public:
 int n;
 int& deconst_n;

 dc():n(0),deconst_n(n){}
 int const_f()const{
  return ++deconst_n;
 }
};

int main(int argc, char** argv){
 dc odc;
 const dc& co=odc;
 int n=10;
 cout<<co.const_f()<<endl;

 return n;
}


P255: mutable最初的名字是 ~const  哈哈哈, 不过我觉得还是~const比较好. 

 

P294: RTTI

class a{int i;};
class b{public: int i;};
class d: public a, public b{public: int i;};

int main(int argc, char** argv){
 d* pdo= new d();
 pdo->i=42;
 b* pb= pdo;

 d* pd1= reinterpret_cast<d*>(pb);
 d* pd2= static_cast<d*>(pb);
 cout<<typeid(b).name()<<endl;
 cout<<typeid(*pd1).name()<<"   "<<pd1->i<<endl;
 cout<<typeid(*pd2).name()<<"   "<<pd2->i<<endl;
 return 0;
}


 P338: 与函数相比异常的频率低的多. 个人以为这个假设不一定成立. 写程序的时候不知道边界情况出现的频率.

 

 

---持续更新分割线---

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值