2014-02-19 24 views
12

我正在研發一款遊戲引擎,目前我堅持設計IO系統。我已經這樣做了,引擎本身並不處理任何文件格式,而是讓用戶通過創建一個*.dll文件來實現他想要的任何內容,其中包含了一些名爲函數的函數。雖然這本身並不是問題,但我主要關心的是在使用引擎期間可能會看到的含義。C++中的度量單位

我設計了一個簡單的resource接口作爲用戶可以考慮的所有事情的基類,我試圖通過將簡單的子類專用於常用數據類型來擴展它,所以用戶不會必須自己實施基礎知識(目前我在考慮audio,image,datamesh)。從audio這個課開始,我已經總結了一個奇怪的問題,同時試圖決定我應該存儲關於採樣率的信息的類型。通常的單位是赫茲,所以我決定把它做成unsigned int

但是這裏有一個小問題 - 如果用戶試圖設置它在千赫?讓我們假設一些抽象文件格式可以將它存儲在兩個單元中片刻。我做了一個簡單的包裝類命名的單位類型:

class hertz{ 
private: 
    unsigned int value; 
    hertz(){}; 
public: 
    operator unsigned int(); 
    hertz(unsigned int value); 
}; 

,並決定讓用戶也可以使用千赫:

class kilohertz{ 
private: 
    float value; 
    kilohertz(){}; 
public: 
    operator hertz(); 
    kilohertz(float value); 
}; 

雖然audio類內部的功能,它可以讓用戶設置採樣率被宣佈爲track& samplingRate(units::hertz rate);。用戶必須通過明確地說,他使用的是什麼量級稱之爲:

someAudioFile.samplingRate(hertz(44100)); 
someAudioFile.samplingRate(kilohertz(44.1)); 

我的問題是:

有沒有更好的辦法來迫使用戶在一個簡單易用的測量單元和優雅的方式?設計模式可能,或者一些巧妙的使用typedefs?

另請注意,在創建引擎的過程中,我可能需要更多的單位,這將與赫茲不兼容。從我的頭頂開始 - 我可能希望用戶能夠通過執行units::rgb(123,42,120)units::hsl(10,30,240)來設置像素顏色。

我試過尋找一個可行的答案,只發現this question,但OP只需要數量級而不確保單位與其他單位不兼容。

另請注意我使用舊的C++版本,而不是C++11。雖然發佈任何版本的解決方案都很好,但如果我也可以使用它,那將是非常好的:)

+1

難道你不能正確記錄你的API嗎? –

+1

是的,爲了避免混淆,也許你應該讓你的API堅持一個標準,赫茲或千赫,而不是兩個。 – leetNightshade

+0

記錄我的API不會改變任何事情,因爲我希望用戶能夠在使用時兼顧兩者 - 例如 - 設置顏色。所以這不完全是一個解決方案。也許它會和赫茲一起工作,但那只是一個單位。 –

回答

17

我知道你提到你不使用C++ 11但其他人在看這個問題的可能,所以這是一個使用用戶自定義文字的C++ 11的解決方案:

http://ideone.com/UzeafE

#include <iostream> 
using namespace std; 

class Frequency 
{ 
public: 
    void Print() const { cout << hertz << "Hz\n"; } 

    explicit constexpr Frequency(unsigned int h) : hertz(h) {} 
private: 
    unsigned int hertz; 
}; 
constexpr Frequency operator"" _Hz(unsigned long long hz) 
{ 
    return Frequency{hz}; 
} 
constexpr Frequency operator"" _kHz(long double khz) 
{ 
    return Frequency{khz * 1000}; 
} 

int main() 
{ 
    Frequency(44100_Hz).Print(); 
    Frequency(44.1_kHz).Print(); 
    return 0; 
} 

輸出:

44100Hz 
44100Hz 
+0

呃...因爲我不能使用C++ 11,所以我會堅持使用我的解決方案。但是如果我有更新版本的IDE,我完全可以使用它。所以 - 我將此標記爲答案,供後人知道:) –

8

Boost「Units」庫對於這種類型的應用程序非常適用。

http://www.boost.org/doc/libs/1_55_0/doc/html/boost_units.html

+1

我不確定這是個好主意。我的意思是 - Boost非常棒,當然可以提供很多,但我認爲這就像在這種情況下使用壓路機打破螺母一樣。會preffer得到一個更簡單的解決方案,不需要額外的庫。雖然這是一個有效的解決方案,所以我現在會立刻讚揚它:) –

+2

@PawełStawarz同意。如果您還沒有使用Boost,那麼開始起來似乎很昂貴/很難。如果你*已經在使用Boost,那真的很簡單。一旦你克服了這個「駝峯」,但是整個世界充滿了偉大的東西等着你! – aldo

+0

還有[PhysUnits-CT-Cpp11](https://github.com/martinmoene/PhysUnits-CT-Cpp11),一個小型C++ 11,用於編譯時尺寸分析的C++ 14頭標庫,以及單位/數量操作和轉換。比Boost.Units簡單,只依賴於標準C++庫,僅限SI,維度的整體冪 –

4

您可以使用factory design pattern來完成您正在尋找的內容。您可以使用私有構造函數和幾個靜態方法創建一個頻率類,這些靜態方法將根據用戶想要使用的單位構建對象。通過保持構造函數是私有的,用戶被迫顯式聲明他的單元,這減少了用戶錯誤的可能性。

#include <iostream> 

using namespace std; 

class frequency 
{ 
public: 
    static frequency hertz(int hz) 
    { 
    return frequency(hz); 
    } 

    static frequency kilohertz(double kHz) 
    { 
    return frequency(kHz * KHZ_TO_HZ); 
    } 

    static frequency rpm(int rpm) 
    { 
    return frequency(rpm * RPM_TO_HZ); 
    } 

    int hz() 
    { 
    return m_hz; 
    } 

private: 
    static const int KHZ_TO_HZ = 1000; 
    static const int RPM_TO_HZ = 60; 

    frequency(int hz) : m_hz(hz) 
    { 
    } 

    int m_hz; 
}; 

int main() 
{ 
    wcout << frequency::hertz(44100).hz() << "Hz" << endl; 
    wcout << frequency::kilohertz(44.100).hz() << "Hz" << endl; 
} 
相關問題