2020年9月4日 星期五

設計 Singleton 模式的插件

這裡的插件是指 CxxlMan2 程式庫的 cxxlObjectPlugin 插件,cxxlObjectPlugin 插件有一個特性,當某個 DLL 檔所提供的所有 cxxlObjectPlugin 物件已無使用者時,這個  DLL 檔就會被卸載。

但 DLL 檔提供的物件若是一般的 Singleton 模式物件,那麼永遠都會有一個不能放棄的持有記錄,即使已無持有者了,這個 DLL 檔也永遠卸不掉。這時可藉由 LifeCustody 這個工具的幫忙,就可以解決這問題。

因要設計成 DLL 和 使用端 兩部份,所以直接提供範例原始檔:
SingletonExample.zip

要編譯這範例須先如下的東東:

  1. CxxlMan2 程式庫 - 抓最版,順便說明檔也一起抓吧
  2. CMRegSelf 插件註冊輔助 - 內附說明
  3. LifeCustody 物件終結插件 - 內附說明

範例有提供 CMake 的支援,編譯不會很難

大致說一下這個範例,test.cpp 定義了兩個 class Input 及 class Output,建立後會各別由 DLL 插件取得 ISingleton 物件,因取得的 ISingleton 是同一個物件,所以 Input::PutStr() 輸入的文字可以由 Output::GetStr() 取出。當兩個 Input 及 Output 物件銷毀時也會通知 DLL 插件銷毀 ISingleton 物件。







2020年6月24日 星期三

函數中的靜態變數

函數中的靜態變數只在第一次呼叫這個函數才會建立,之後不管呼叫幾次都用的都是同一個,包括成員函數也一樣。如以下的範例:
 
#include <iostream>

using namespace std;

class A
{
  int m_v;
public:
  // Constructor
  A(int v)
  {
    m_v = v;
  }

  void Show()
  {
    cout << "數值:" << m_v << endl;
  }
};

class B
{
public:
  // Constructor
  B()
  {}

  void Show(int v)
  {
    static A a(v); // 函數中的靜態變數
    a.Show();
  }
};


int main()
{
  B b1;
  B b2;

  b1.Show(1); // 第一次執行會設定靜態變數,往後用的都是同一個
  b1.Show(11);

  b2.Show(2);
  b2.Show(22);

  return 0;
}




2020年6月10日 星期三

Template cxxlObjectPlugin 插件

這是個範例,用來示範如何把 template class 做成 cxxlObjectPlugin 插件,下載點:
Template cxxlObjectPlugin.7z

因範例是用 Console 視窗顯示 utf-8 文字,所以先參考 修改 Win10 的 Console 視窗顯示 UTF-8

因 cxxlObjectPlugin  插件須在執行時期經由 CM 在 .cpp 程式中建立,而 template class 則是在編譯時期就須產生物件,解決的辦法是把產生 template class 物件的程式碼帶到 .cpp 中執行。見 Plugin.HPP 中 IPlugin1<T>::Create() 的做法,而在 Plugin.cpp 中 IPlugin1_New() 負責執行以產生 IPlugin1<T> 物件。

一般來說 cxxlObjectPlugin  插件會做成 介面類別 <-- 實作類別 的繼承架構,IPlugin2<T> 就試圖這樣搞,但實作類別會在 .cpp 中,編譯完後早就寫死了,如何去繼承 template 介面類別, IPlugin2<T>::Create() 就試圖這樣搞,但沒成功。


修改 Win10 的 Console 視窗顯示 UTF-8

如下圖做修改就行了,在 C 只要 setlocale(LC_CTYPE, "C") 就可以顯示 utf-8


2020年4月20日 星期一

白話設計原則

  • 里氏替換原則(Liskov Substitution principle)
    是對子類別設計的勸說或約束,要求在不修改使用端的程式演算法之下,使用到父類別實例的地方,改用子類別的實例去替代,都不會出錯

  • 依賴反轉原則(Dependency inversion principle,DIP)
    古老以前,要設計上層的的功能,得須了解下層元件有哪些功能再針對這些元件去設計,設計完之後,上層就被這些元件綁死了,上層強烈依賴下層,而且耦合度非常高。後來改成要下層去依照上層的需求來設計元件,所以才叫依賴反轉。
    不過現在一般都是依賴在一個介面,上層依介面提供的功能來使用,下層依介面設計提供服務的元件,而且耦合度降低。而介面標準也成了兵家必爭之地。

  • 開閉原則(對擴展開放,對修改封閉)
    概念上是說一個類別設計完成之後,就不應再去更動它,若要增加新功能,應該用繼承或組合去擴展,也就是說用擴展代替修改。

  • 封裝變化
    是指須要修改程式碼的部份獨立出來,通常都用策略模式來解決

  • 單一職責原則(Single responsibility principle)
    簡單地說就是類別的合理分割,但問題就在怎樣分割,分割到怎樣的程度才叫合理,十個人做十個都不一樣,只能說設計時要盡量考量清楚,途中有發現不適合也要大膽改正,畢竟日後的維護要比設計時花更多的精神和時間

  • 介面隔離原則(英語:interface-segregation principles)
    對於特定的使用端(角色)只提供符合它的介面給它用就好,實際運作的物件不要暴露給它。


2020年3月3日 星期二

莫名其妙的問題

以下程式使用 MinGW 8.1.0 64位元版(x86_64-posix-seh) 編譯

採用 Release 和 Debug 兩種模式編譯的執行結果不一樣(另人傻眼)

本來想說是不是編譯器的 bug,但有以下的訊息:
the compiler can assume that the address of 'p' will never be NULL [-Waddress]

更另人傻眼了

2020年2月21日 星期五

武漢病毒酒精稀釋公式推導

由於 75% 消毒用酒精缺貨,若能拿到 90% 清潔用酒精來稀釋也是個辦法,不過不可以直接使用自來水,而是要用 RO 過濾水。以下是稀釋公式的推導。

首先須釐清問題已給出的相關資料:
  1. 溶液(Solution)是指含有溶質(Solute)和溶劑(Solvent)的混合物,即
    溶液 = 溶質 + 溶劑
  2. 溶度(Solubility) 為 $\frac{溶質}{溶液} \times 100\%$

2020年1月15日 星期三

打造在 Win10 的 C++ 編譯環境

此文有點像廢文,因每人須求不同,所以做法也不一樣,所以只能說給大家作為參考。

這裡用的編譯器是 MinGW 系列,可到這裡下載,至此文發佈時間為止,提供了如下最新的版本:
▲MinGW 各版本列表