re: 碩士論文致謝 Kevin Lynx 2010-04-29 16:37
好吧。原來你也認識潘李亮。。。
re: [轉載]低耦合模塊間的通信組件:兩個模板 Kevin Lynx 2010-04-21 16:31
不明真相地路過。。。
re: 畢業設計截圖(計算機圖形學) Kevin Lynx 2010-04-20 09:55
- -#
博客后臺管理:文件->上傳即可
re: [總結]中間/目標代碼生成 Kevin Lynx 2010-04-10 17:04
@陳梓瀚(vczh)
我當時想試試直接生成代碼的感覺,因為看到lua就是這樣做的。:D。所以就折騰了下自己。
PS,美帝不錯吧。
re: 討論:單件模式的優點何在?有無存在的必要? Kevin Lynx 2010-03-29 13:37
@溪流
這個問題某種角度來看,就如同對成員變量不管應用情景如何都提供Get/Set一樣,同public一樣了。
我覺得唯一的區別,還是一種安全控制吧:
class Singleton
{
public:
static Singleton &GetInstance() { static Singleton ob; .... }
private:
Singleton() { ... }
Singleton( const Singleton & ) ...
};
那么,這個Singleton對象就只存在一份。
當然,也有單件不作constructor的private限制的。
re: lua和python誰更適用于嵌入MMORPG? Kevin Lynx 2010-03-22 20:48
@aydge
lua里的線程并非OS里的線程。大家都知道的WOW里的LUA,用于其客戶端的UI擴展制作。本文提到的應用主要集中于服務器端的邏輯擴展,如任務、劇情等。
沒想到這種東西有這么現成的。我們還是自己寫的崩潰捕獲。可以根據pdb文件dump出崩潰時刻的調用堆棧之類的。收藏了。
對這種支持多種字符串資源的問題,沒必要自己寫個程序去生成對應的代碼文件吧?
english_res.txt:
IDS_TYPE_ERROR "XXXXX%s"
const char *s = LoadString( IDS_TYPE_ERROR );
sprintf( buf, s, err );
re: 簡要實現正則表達式匹配字符串[未登錄] kevin lynx 2010-02-20 19:34
@feizai
是啊。
re: 需要判斷指針為空嗎[未登錄] kevin lynx 2010-02-11 10:49
這個問題在我們組里也備受爭議。有人覺得對每個指針進行拿捏然后再決定判斷,很多余,所以索性對所有指針進行空判斷;有人覺得沒必要寫那么多冗余代碼,需要對每個指針進行上下文審查。
拿一個接口為例,接口實現里是否有必要對參數進行判斷?接口調用者是否需要對返回值做判斷?反正這種事情挺糾結的.
re: 靜態庫中全局變量的初始化問題 Kevin Lynx 2010-02-10 16:43
@金慶
@李現民
3q for your comments.
今天隨便看了個文檔
http://linux.chinaunix.net/bbs/thread-910296-1-1.html,<Linker Algorithm.pdf>恰好在里面看到和我這里提到的相同的2點結論
re: WOF(名將三國)的TGL文件格式 Kevin Lynx 2010-01-26 08:53
@飯中淹
- -
詭異。。我還以為你發漏了。我還用OD反匯編查找了下字符串。
re: WOF(名將三國)的TGL文件格式 Kevin Lynx 2010-01-25 14:28
占位置。學下破解思路。
PS,你那個工具怎么用?貌似需要將TGL文件放在同目錄且改名為stand_1.tgl ?
re: 靜態庫中全局變量的初始化問題 Kevin Lynx 2010-01-20 09:14
@OwnWaterloo
一樣的。
re: 靜態庫中全局變量的初始化問題 Kevin Lynx 2010-01-18 08:52
@OwnWaterloo
這個機會是什么意思?
re: 靜態庫中全局變量的初始化問題 Kevin Lynx 2010-01-17 23:00
@OwnWaterloo
@LOGOS
加extern是什么意思?文章中的例子,只是因為鏈接器沒有為靜態庫中的全局對象生成初始化代碼。我也并不關心每一個local的初始化順序,因為他們是全局的,所以他們肯定會先于main被初始化。整個文章的意思,其實是說,鏈接器并沒有生成這個自動初始化的代碼,因為鏈接器覺得這幾個“沒有”被使用的全局對象不需要,所以就沒生成。
圍觀悲劇的樓主。。。語言設置問題。可能是你設置被reset了
re: 2005-2009年個人總結 Kevin Lynx 2009-12-24 09:11
怎么像臨終感言。。。
re: 很傻很天真之Array Kevin Lynx 2009-10-12 09:19
- -|
重載逗號運算符,不會改變函數中逗號的語義。 - -!
是用于改變逗號表達式中逗號的語義,如:
ArrayDimension a;
a, 1; //逗號表達式
標準的逗號表達式其實還應該有個返回值。如:
class Test
{
public:
Test( int i ) : index( i )
{
}
const Test &operator, ( const Test &other )
{
return *this;
}
private:
int index;
};
Test a( 1 ), b( 2 ), c( 3 );
c = a, b;
不懂C#里的動態多維數組,所以對你這里的需求不作評論。:)
如果要支持不定個數的參數,要么使用C里的...(如printf),要么重載很多版本,即使模板也無法解決這個問題。如果太懶不想寫那么多重載版本,可以考慮用宏自動生成這些代碼。
re: HGE核心函數注釋 Kevin Lynx 2009-09-20 15:23
應該去分析下graphics.cpp下的圖形渲染部分。
re: 懷念 —— 與大牛一起度過的日志[未登錄] Kevin Lynx 2009-09-03 14:04
大致瀏覽了你BLOG的所有文章,鼓勵下你。加油。
re: 使用std::vector 的陷阱[未登錄] Kevin Lynx 2009-09-03 13:37
其實我覺得這不是vector給你設的“陷阱”,STL容器只有責任維護你給他的東西,但沒理由維護這個東西里面的東西。不僅僅是vector,STL所有的容器如果按你這種思維去用,都會出問題:
class Test
{
int *a;
~Test()
{
delete a;
}
};
std::vector<Test> 維護Test::a其實應該是你的責任。
re: 怕了開源跨平臺的東東了[未登錄] Kevin Lynx 2009-09-03 13:32
剛開始肯定會不習慣。很多開源項目會依賴第三方庫,但是下載下來的包里一般都不帶第三方庫。得自己去找,還得保證版本一致。習慣就好了,總比讓你重頭自己寫個UI庫好吧。:)
re: 低耦合模塊間的通信組件:兩個模板 Kevin Lynx 2009-08-23 16:13
@OwnWaterloo
其實工作量這事,本來也就沒有被減少。就工作量(代碼量)這個角度來比較兩者的話。OnE1 OnE2和OnEvent(以后討論就說前者后者)比較而言,在增加新的事件通知時,前者需要增加通信層接口聲明(也就是那個被UI繼承的基類);后者需要從Param逐個取數據,前者是直接在參數里,如果前者也使用Param或者tuple來組織參數,也免不了解參數。
我覺得后者較前者讓人爽的好處就是:永遠不需要改這個中間通信層。
說下我現在是怎么派發通知的,這個其實也被放在這個通信中間層:
class OpNotify
{
typedef void (*HandleNotifyFnT)( any *data );
public:
AddNotifyHandler( long event_id, HandleNotifyFnT fn );
void Notify( long event_id, any data );
private:
std::map<long, HandleNotifyFnT> handleFuncTable;
};
UI層需要注冊處理事件通知的函數到handleFuncTable里。邏輯層每次派發事件通知時,調用OpNotify::Notify,這個函數簡單地從handleFuncTable里找對應的處理函數。
這個樣子之后,避開了switch...case。誰都知道,隨著事件類型的增加,switch...case也將急速膨脹。進一步地,通信中間層永遠不需要修改了。
現在邏輯層派發事件通知時:
OP_NOTIFY( NT_ENTER_RGN, any( create_param( player, rgn_id ) ) );
// OP_NOTIFY被定義為OpNotify::Notify
UI層只需要定義NT_ENTER_RGN的處理函數,并注冊到OpNotify,該處理函數大致為:
void HandleEnterRgn( any *data )
{
typedef Param2<Player, long> ParamType;
ParamType *p = any_cast<ParamType>( data );
Player *player = p->p1;
long rgn_id = p->p2;
}
re: 低耦合模塊間的通信組件:兩個模板 Kevin Lynx 2009-08-23 15:31
@OwnWaterloo
是啊。嚴格來說,不算降低耦合。因為UI和邏輯層確實得協商設置哪些通知事件。不過,反正這個邏輯模塊本身就是要通知UI事件觸發的。這樣做之后,邏輯模塊不需要管UI是否處理,只需要通知。在任何地方想怎樣通知就通知。整個程序換了UI后,邏輯層也不需要改,只改UI的通知處理即可。
另一方面,如果使用
void OnE1(tuple<e11,...> );
void OnE2(tuple<e21,...> );
void OnE3(tuple<e31,...> );
這種方式,就會涉及到添加很多通知接口。這個負責通信的中間層就會越來越龐大。雖然,OnEvent(int e, any );這個方式會導致添加越來越多的事件類型定義,但總比添加一個OnEn好吧?:)
很少做這種UI比較復雜的應用程序,不知道其他人有沒有好的模塊架構方法。實在不想把UI和邏輯揉得那么緊。看過一些人直接在MFC的OnXXX里寫一堆邏輯代碼就覺得受不了。 我現在做的東西里就包含MFC和控制臺兩套UI,甚至在GUI方面差點換到bcb。
re: 低耦合模塊間的通信組件:兩個模板 Kevin Lynx 2009-08-23 13:38
@OwnWaterloo
對,就是你說的這個意思。我也記得有個tuple這個東西。但是我一般不用boost,太大,太多。可以用來學習。:)
re: 指針和模塊健壯 Kevin Lynx 2009-08-18 11:54
@lin
當時那個BUG是因為C++代碼中對某個指針沒判斷,而由于某些臨界條件就會導致這個指針為NULL。恰好可以通過在策劃的腳本里做些修改而避免程序里那段代碼的執行。這個跟具體的應用環境有關系,別誤會。
re: 強大的bcb Kevin Lynx 2009-08-15 14:02
@OwnWaterloo
3Q
@艸
你就解釋下我遇到的那些“BUG”是怎么回事就行了,就事論事。或者你可以告訴我,new std::ofstream在你的BCB上沒問題。你的程序編譯時不會出現F1004 Internal compiler error。
re: 用腳本實現副本 Kevin Lynx 2009-07-16 22:10
應該不是“用腳本實現副本”,我覺得應該是提供腳本接口給策劃來創建副本。副本在很大程度上還是按照一般場景被服務器管理。
re: 實現functor - 增強型的函數指針 Kevin Lynx 2009-07-08 10:30
@deadlm
- -|
re: 實現functor - 增強型的函數指針 Kevin Lynx 2009-07-05 22:40
@deadlm
沒用過pascal,不同語言帶來的感受肯定不同。:)
functor之類的東西,為了支持各種不同類型的函數,其內部實現確實很惡心,而且少不了復制代碼。后來發現有宏遞歸這種東西(
http://www.shnenglu.com/kevinlynx/archive/2008/08/20/59451.html boost中甚至直接有個macro庫),雖然內部實現可以少寫些代碼(用宏來幫助生成),但是其代碼看起來更糾結。:D
re: 實現functor - 增強型的函數指針 Kevin Lynx 2009-07-05 16:50
@deadlm
functor這種東西本質上確實如你所說是保存一個“函數”指針。其實偏要加上返回值類型以及各個參數的類型,我覺得主要還是哄好編譯器。
void func( int );
void func( int, char );
這兩個函數在語言層次畢竟屬于不同的類型,functor在回調他們時,需要知道傳多少個參數。這些信息都需要保存起來。
template在整個C++中完全屬于一種花哨的東西,當然不可否認其作用,如果實在煩這些,可以無視這些語言特性。
之所以我不敢“蔑視”STL、LOKI之類的庫,是因為我自認能力沒到這級別。也許以后我可以。
class lua_binder<R ( P1 )> 是lua_binder的偏特化,因為lua_binder本體只有一個類型參數,所以,不能寫:
class lua_binder<R, P1>。這么說來,在支持多參數函數的情況下,要么使用functor<int, TYPE_LIST1( ...的形式,要么使用functor<int (int)>的形式。對于functor<int, int>的形式,你指的是怎樣的實現?(很久沒在弄模板這些東西,有點生疏)。
re: 實現functor - 增強型的函數指針 Kevin Lynx 2009-07-04 17:56
@deadlm
并不見得functor<void, int, char>就比function< void, TYPE_LIST2( int, char )>好。
functor<void, int, char>是需要諸如:
template <typename R, typename P1>
class lua_binder<R ( P1 )>
的語法支持。而并不見得所有的編譯器都支持。另外,我沒有提供這樣的接口也并不見得我寫不出來:
http://www.shnenglu.com/kevinlynx/archive/2008/08/20/59451.html
http://www.shnenglu.com/kevinlynx/archive/2008/08/13/58684.html
另外,這里的TYPE_LIST機制取自于loki庫。佩服哥們有蔑視loki庫的魄力。
re: 基類角色之對象管理器 Kevin Lynx 2009-07-02 17:24
雖然不是很明白飯中淹關于LINK對象的意思,但是我獲得了靈感,寫了下面的代碼:
///
///
///
#include <stdio.h>
#include <list>
class ref_op
{
public:
virtual void be_null() { }
};
typedef std::list<ref_op*> RefOpList;
class ref_base
{
public:
~ref_base()
{
clear_ops();
}
void add_ref( ref_op *op )
{
_oplist.push_back( op );
}
void clear_ops()
{
for( RefOpList::const_iterator it = _oplist.begin();
it != _oplist.end(); ++ it )
{
(*it)->be_null();
}
}
private:
RefOpList _oplist;
};
template <typename _Tp>
class auto_null : public ref_op
{
public:
void fetch( _Tp *t )
{
_t = t;
t->add_ref( this );
}
auto_null<_Tp> &operator = ( _Tp *t )
{
fetch( t );
return *this;
}
void be_null()
{
_t = 0;
}
operator _Tp*()
{
return _t;
}
private:
_Tp *_t;
};
//////////////////////////////////////////////////////////////////////////////
class CMonster : public ref_base
{
};
class CMonsterAI
{
public:
void SetOwner( CMonster *pOwner )
{
m_Owner = pOwner;
}
void Test()
{
if( (CMonster*)m_Owner == NULL )
{
printf( "The owner is null.\n" );
}
else
{
printf( "The owner is NOT null.\n" );
}
}
private:
auto_null<CMonster> m_Owner;
};
int main()
{
CMonster *pMonster = new CMonster();
CMonsterAI *pAI = new CMonsterAI();
pAI->SetOwner( pMonster );
pAI->Test();
delete pMonster;
pAI->Test();
delete pAI;
return 0;
}
CMonster內部會保存一個CMonster的指針,當CMonster被刪除掉時,會自動更新CMonsterAI內部的CMonster“指針”為NULL。接口比較簡單:1)在會被引用(即被其他對象保存其指針)的類設計中派生(或組合)ref_base類,ref_base類簡單來說就是保存一個引用類對象列表,通過基類ref_op可以使得ref_base保存不同類型的引用類(例如CMonsterAI可以保存CMonster, CRegion也可以保存CMonster),ref_base在析構時自動回調引用類對象的be_null函數,be_null函數在auto_null類中自動把CMonster*設置為NULL。
通過重載operator=,使得SetOwner函數里不需要做其他操作(看起來)。
re: 基類角色之對象管理器 Kevin Lynx 2009-07-02 14:10
本質上就是通過讓其他模塊不保存這個object的直接指針,而是一個ID,然后通過一個manager由這個ID而獲取到這個object*,是可以有效減少指針無效的問題。但是,面對的最大問題就在于這個查找過程。你這里用的是std::map,我們用的是stdext::hash_map,我自己都覺得有點速度問題。希望能在這個問題上找到良好的解決辦法。:)
re: USACO 3.1 Stamps Kevin Lynx 2009-07-01 08:55
不要再在首頁發布這些東西了。基本上只有代碼,不知道發首頁的目的是什么。我的RSS READER訂閱了CPPBLOG首頁,但全是你的東西。
這個測試例子確實有問題。把一個對象(shared_ptr)和一個指針(string*)分別作為map的key,對象肯定會比指針慢。對象用于map的key會涉及到很多復制操作。
@owlcn
應該不支持重入。因為都是對同一個lua_State操作。
re: GDI+中從內存讀取圖片/保存圖片到內存 Kevin Lynx 2009-06-20 10:58
@mike7734@sina.com
你最好找人發一份c++ primer給你。:)
@adie
剛正在看vc2005中的xtree找原因。在_Lbound中,確實是因為_DEBUG_LT_PRED導致DEBUG和RELEASE使用了不同的代碼。而且確實是因為_Lbound是const的才導致this->comp也是const的。但是,在看到你評論之前我還沒反應過來:因為this->comp通過作為函數參數而去掉了const修飾,囧。
起碼真相大白了。3Q
@adie
1.我這里說的predicator,指的是less本身。包括傳給find_if的functor,都被我稱為predicator。STL內部保存這種predicator,都是以value的形式保存。既然是value的形式,就不會存在調用這個predicator的operator()必須要求其為bool (*)() const類型的。以前沒搞清楚這個問題,現在也沒關注過。
你舉的例子中,談的是這個predicator的bool operator()( ...)成員函數的參數為const&。對于less而言,它的這個operator()的參數是map內部保存的element。無論是從效率還是其他方面,是肯定要const&的。
2.初始化順序這個問題,我對鏈接器細節沒怎么關注過。不過,情況可能真如你所說。謝過。
re: 實現一種解釋性腳本語言(一) Kevin Lynx 2009-05-23 17:05
@AJkm
是的。:)
@小馬
為什么你不打開libevent的源代碼搜索下evbuffer呢??
@小馬
在我印象里,evbuffer用于緩存邏輯層(即l基于libevent那一層)將要發送的數據,以及緩存從設備(fd)里讀取出的數據。
re: VS 2010 C++ 王者歸來 Kevin Lynx 2009-04-28 13:46
個人從來沒有認為C/C++就是窮途末路。技術環境在浮躁,也不至于認為某個語言不行了。
C++0x的新特性看起來還比較有趣。
re: 終于買到了《Unix編程藝術》[未登錄] Kevin Lynx 2009-04-08 17:12
灌水,支持<unix編程藝術>
@happyday
代碼確實粘貼錯誤,謝謝提醒。
@無名
圖確實存在問題,謝謝提醒。
文章已做過微小修改。
re: 自己實現memcached客戶端庫[未登錄] Kevin Lynx 2009-03-26 18:05
@阿斯蒂芬
能不能具體點?哪個文件,哪一行?
我稍微搜索了下代碼,發現只有在fun_test.txt里才有sizeof( addr ),這個文件是用于功能測試的,只要kl_memcached下的源文件編譯得過你就可以使用。:)