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的時候必須事Crowdsourced Security Testing道這個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: 與函數相比異常的頻率低的多. 個人以為這個假設不一定成立. 寫程式的時候不知道邊界情況出現的頻率.
---持續更新分割線---