2013-04-26 71 views
-1

是否可以創建一個靜態創建的類實例,但帶有參數?這是我對記:靜態創建的全局類實例,帶參數

/* main.cpp */ 
    int main(int argc, char ** argv){ 
    /* obtain parameters from command line and pass one of them to CLog*/ 
    } 

/* CLog.h */ 
    class CLog{ 
    operator <<(); 
    /* some other stuff */ 
    }; 

    extern CLog log; 

總之,我想這個類是所有類都可以訪問在我的項目,從而extern,我希望它可以創建非指針(允許輸出與log<<"something"),但我想在創建它之前傳遞一個參數。那可能嗎?或者是否有解決方法,以便我不必將其稱爲(*log)<<"something"

+0

就像添加一個成員函數來設置參數一樣,並且在'main'函數中儘快被調用? – 2013-04-26 10:54:24

回答

2

在調用main之前創建的log因此您無法在main之後傳遞需要準備的參數。您可以以這種方式傳遞參數:

class CLog{ 
    void setParameters(...); 
    ... 
    /* some other stuff */ 
}; 

extern CLog log; 

...

int main(int argc, char ** argv){ 
    log.setParameters(...); 
} 
2

你不能直接這樣做,因爲全局在您main開始運行之前進行初始化。你可以,但是,創建一個解決方法與placement new

#include <new> 

char CLogBuf[sizeof(CLog)]; 
CLog* pLog = nullptr; 

int main(int argc, char** argv) 
{ 
    pLog = new (CLogBuf) CLog(params); 
    return 0; 
} 

是否值得這是你的決定。更直接的解決方案將是@ M.M提出的解決方案。

繼和意見的討論,這裏是引用的,而不是指向一個版本,允許保留原有的接口:

#include <new> 

char CLogBuf[sizeof(CLog)]; 
const CLog& log = *((CLog*)CLogBuf); 

int main(int argc, char** argv) 
{ 
    (void) (new (CLogBuf) CLog(params)); 
    return 0; 
} 
這種做法的

主要優點是接口到所需的最低限度的減少:無防止由不同方多次調用初始化方法,很可能破壞程序語義。這種方法完全消除了init方法,從而消除了這個問題。

+0

+1我喜歡這個想法(即使我更喜歡原始的reinterpret_cast,因爲它不需要放置新的或緩衝區,只需要一個普通的指針)。由於OP不需要一個指針(爲了避免對其進行解引用),爲什麼不只是一個引用呢?除非它會觸發UB(我不確定)? – syam 2013-04-26 11:23:57

+0

@syam演員在這裏是多餘的,這就是爲什麼我刪除它。我不確定你的意思是不需要放置新的或緩衝區 - 構造函數需要被調用,你不能創建未初始化的引用。是的,指針僅通過語法改變原始界面。參考是一個有趣的想法。就像'const CLog&log = *((CLog *)CLogBuf);'雖然需要定義一個返回引用的特殊版本的placement new。 – SomeWittyUsername 2013-04-26 11:46:10

+0

「*你的意思是不需要放置新的或緩衝區*」=>因爲它代表你的代碼歸結爲'CLog * pLog = nullptr;/* ...後來主要是:*/pLog = new CLog(params);',緩衝區和放置位置也是多餘的。至於我的參考思路:'char CLogBuf [sizeof(CLog)]; CLog&log = * reinterpret_cast (CLogBuf); /*...主要內容:*/new(CLogBuf)CLog(params);' – syam 2013-04-26 11:57:45

0

我喜歡在這種情況下會在整個代碼中使用一個訪問器,它通過引用爲callsite方便返回單例。訪問者的實現可以簡單地取消引用現有的全局,也可以用給定的參數延後創建它,就像這樣:一個

// In public header: 
extern CLog & Log(); 

// In private cpp: 
extern CLog & Log(); 
{ 
    static CLog * pLog = nullptr; 
    if(!pLog) 
    pLog = new pLog(/* params, which could be fetched from command line outside of main */); 
return *pLog; 
} 

// In client code: 
Log().DoSomething(); 

如果你不喜歡的括號,真想外觀對象引用,你可以創建一個包裝對象並通過operator->訪問懶惰創建的CLog,就像智能​​指針一樣。

+0

如何將外部參數傳遞給構造函數並不十分清楚。除此之外,這正是OP不想做的 - 動態實例化。 – SomeWittyUsername 2013-04-27 05:29:48