看板 C_and_CPP 關於我們 聯絡資訊
※ 引述《EdisonX (閉上眼的魚)》之銘言: : : Q1 class with function pointer : : 一種方式是在 C1 裡面塞外部的 function pointer : class C1{ : private: : double (*fptr)(double) ; : public : : C1 ( double (*fptr_)(double) ) : fptr (fptr_) {} : double run(double low, double up) { : fptr(low); .... fptr(up); : } : }; : 這種方法好處是可以多弄一個 setter , 隨時改掉 fptr 指向函式 : < 又是一個問題,我不知道這種 class 大多從頭到尾指向一個 function, :  還是可以中途切到其他的 function 去 ... >   這個方式的耦合度比較低, 也可以隨時換 strategy 但是如果該 function 需要帶 context, 就要用 std::function + std::bind : 另一種方式以 pure virtual function , 便必需強制繼承撰之 : class Base { : prvate : : virtual double fitness(double) = 0; : public : : double run(double low, double up) { : fitness(low), ..., fitness(up); : } : } 繼承關係的耦合度很強, 看你怎麼抉擇 : 另外,好奇有沒有像這種東西 < 我知道它是錯的 orz > : class C <typename Func> { : public : : double run(double low, double up) { : Func(low), ... , Func(up) ; : } : }; 有, 但是有點差異: template< typename Function > double run( double low, double up, Function f ) { f( low, up ); } 這樣它會自己推導 prototype : 請問一般在設計時會怎做 ? 老問題, 設計 API 最後就是選擇, 沒什麼標準答案 : Q2 我真搞不懂 template 該什麼時候拿出來用.. : : 有些 template function 確實是很直覺有個設計之範本,如 : template <typename T> : T MaxVal(T* beg, T* end); : template <typename T> : T Sum(T* beg, T* end); : 納悶的是一些明明很特別的數值計算上,比方說算平均值好了 : 這個很明顯最後傳回的會是 double,還有必要做成 template 嗎? : template <typename Tin , typename Tout> : Tout Average(Tin* beg, Tin* end); : < 其實我更納悶的是, std::complex 做成 template 有必要嗎 ? > : < 一般在做的時候不都是直接塞 double 進去就好了 ? > 有的時候你可能會想塞自己做的數值型態 比方說一個 class Double 對精準度有做特化 那麼這個 class 可以直接丟進去, 一樣受益於既有的演算法 : : Q3 <牛角一> : operator == 是單元運算子,但有時候... : : 在判斷是否相等之情況下 : class C { : private : : double num; : public : : bool operator == (const C& other, const double eps=1E-9) const { : return fabs (num - other.num ) <= eps; : } : }; 雖然不是重點, 但這裡語法錯誤 基本上 operator overloads 最好都寫成 friend free function : compiler error, 不意外。目前想到折衷的做法是 : 新增一個 static data member, const static double eps , : 但其初值便只能用 coder 自定吧 ? : 若使用之 eps 不同時就不能用 == , 必須再額外寫一個 : bool C::IsEqu(const C& other, const double eps = 1E-9) const; : 還是這部份根本沒人在鳥 floating error ? 我看不太懂這段, 但是 const double 在這裡是無意義的 因為 pass by value 之後 eps 的值本來就不會有 side effect : : Q4 <牛角二> : overload subscript of subscript operator... : : 簡單的說是這個東西 : template <typename T> : class M{ : public: : T operator [][] (const size_t row, const size_t col) ; : }; : 請問,唯一方法是否只能架構起類似 vector<> 的東西,再用繼承方式處理嗎 ? : ( 這裡也是一個問題 , 我認為用 "包含" 較佳 , 但一些設計是用繼承處理 ) : 這裡我沒打算用 std::vector 原因是認為對 Matrix 而言, : col / row 一旦固定幾乎不會變, : 用 vector 在效能與空間管理上「主觀」認為並不吃香, : 不知我的想法是否有誤 ? 基本上, 你的 Matrix 可以 overload [], 讓它回傳 Row 這個 Row 可以再 overload [] 一次 另外 vector 在空間與效率上反而是最好的, 因為 1. 空間連續 2. 它的額外成本很低 3. 你幾乎不需要刪除節點, 所以它要 realloc 的機率很低 真的覺得不放心的話 可參考 boost::array : PS : : 我是有想過用這種方式去做 : template <typename T, const size_t row, const size_t col> : class M { : T arr[row][col]; : }; : 一樣產生兩個問題 , 這種方式應是放在 stack, 可使用量較小, : 另一問題又回到 operator [][] 方面, : 目前想過可以用 T operator( const size_t row, const size_t col) ; 方式做 : < 但總覺得寫起來很不順 > : : Q5 <牛角三> : 防呆問題 : : 1. 到底是誰該負責準確性 ? : // < part 1 > : double div(double a, double b) { : return a/b; : } : double a, b, c; : if(fabs(b) > eps) c = div(a,b) ; : else /* error handle */ : // < part 2 > : double div(double a, double b) { : assert(fabs(b)>eps) : return a/b; : } : double a, b, c : c = div(a,b); : 一般而言是弄得像 part1 還是 part 2 ? : 或 , 這是公司內互踢皮球的開始 ? 文件講好就好, 這是政治問題 這也呼應了上述 Q2, 保留彈性總有一天會用到 : 2. 記憶體不夠到底要不要處理 ? : 一般抓到什麼除零錯誤、字串格式不對 都還有可議空間 , : 把有問題的那段抓出來分析還有機會改善。 : 但判定 allocate memory fail 時 : new fail. malloc fail. 有不同方式可 catch , : 除了 log 紀錄起來、程式強制退出,還有其他處理方式嗎? 這邊很複雜, 建議可參考 More Effective C++ 最後幾個章節 專門講述你要怎麼在記憶體不足的情況再擠出空間 但強制退出也是一個可接受方案 : ------------------------------- : 小弟學不專精,問題有些多,煩請不吝賜教。 : 謝謝各位。 -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.115.53.41
loveme00835:using friend function is bad idea in this 06/01 20:02
loveme00835:situation, becuz operators just provide convenient 06/01 20:03
loveme00835:ways to interactive with objects, but that should 06/01 20:04
loveme00835:the 'only' way to do this, so ususlly objects also 06/01 20:05
loveme00835:give you methods like a.equals(b) 06/01 20:05
legnaleurc:我覺得不需要太妖魔化 friend, 因為 C++ 缺乏 package 06/01 20:29
legnaleurc:scope permission, 另外, operator 的另一個好處是它可 06/01 20:29
legnaleurc:以跟 primitive types 的操作一致化, 對於數值語義來說 06/01 20:30
legnaleurc:有其好處 06/01 20:31
loveme00835:you're right, but it might increase probability of 06/01 20:34
loveme00835:ambiguous function calls 06/01 20:35
legnaleurc:等等, 我覺得我們在講的論點我好像在 news group 上看 06/01 20:38
legnaleurc:過 XD 反正各有優缺點, 最後都是選擇問題 06/01 20:39
EdisonX:Q3 的部份我補充一下,實際上是 class complex 實作上我的 06/01 20:42
EdisonX:作法,在判斷兩個norm是否相同時,考慮浮點數誤差,所以會有 06/01 20:42
EdisonX:eps,原意operator==那裡可能語法真不容許,故問一般強調的 06/01 20:43
EdisonX:eps不同時,只剩 member func./friend func. 一路而已吧 ? 06/01 20:45
legnaleurc:同樣的功能, 同時提供 operator 和具名函式的做法也不 06/01 20:47
legnaleurc:少, 如果讓我設計的話, 我會使用 static member 06/01 20:48
legnaleurc:operator 的版本使用 static member 的 eps 06/01 20:49
EdisonX:指的是文中提到的 Complex::static const double eps 嗎 ? 06/01 20:49
legnaleurc:具名函式讓 client 指定 eps, 這沒有定論, 不要太違反 06/01 20:50
legnaleurc:直覺就好 06/01 20:50
loveme00835:用proxy多型取得誤差值,此法每個物件要keep指標,可 06/01 20:50
loveme00835:以執行期更換criteria,不一致再比較取小者 06/01 20:53
EdisonX:疑!love~大的方法似乎也可每個物件都一個 eps 取小實現. 06/01 20:56
EdisonX:此討論串真是受益良多.再次感謝不吝指導 :) 06/01 20:57
EdisonX:補個推, 謝謝 legnaleurc 細心的回覆, 一點 p 幣請笑納。 06/01 21:01
legnaleurc: :) loveme00835 展示的方法都很實用, 我也見識不少 06/01 21:32