re: 一個有趣的小問題 OwnWaterloo 2009-09-01 21:37
@莫失莫忘
靜態成員本來就可以通過
1. 類名
S::sum
2. 實例
S s;
s.sum;
兩種形式訪問, 毫無區別, 推薦第1種形式。
this->sum 依然是 S::sum, 而不會是s的非靜態成員。
它根本就沒有非靜態的sum, 難道編譯器還因為this->sum專門給它再加這么一個非靜態sum么?
re: 一個有趣的小問題 OwnWaterloo 2009-09-01 21:31
@莫失莫忘
你是從那句解釋中看出有解引用一說的?
re: VC6中的簡易delegate實現 OwnWaterloo 2009-09-01 20:54
@李現民
如果樓主打算試試boost.function on vc6, 請告知下結果哦~~~
我對vc6吐出的錯誤有些恐懼~~~
re: VC6中的簡易delegate實現 OwnWaterloo 2009-09-01 20:50
@李現民
boost.function有3種使用語法:
1.
function<void ()> ...
function<void (int) > ...
function<int (std::string,int) > ...
2.
function<void> ...
function<void,int> ...
function<int ,std::string,int > ...
3.
function0<void> ...
function1<void,int> ...
function2<int ,std::string,int > ...
越往后, 語法越丑陋, 但受更多編譯器支持。
可以試試在vc6上是否支持boost.function的2使用方法(第1種就不要指望了~~~)
如果行, 就看boost是怎么做的。
我估計后一種語法的實現依然要偏特化, 所以不行。
那就只能使用最丑陋的第3種語法了。
re: 低耦合模塊間的通信組件:兩個模板 OwnWaterloo 2009-08-23 15:50
@Kevin Lynx
我說說我的看法啊, 你看看是否合理。
將:
void OnE1(tuple<e11,...> );
void OnE2(tuple<e21,...> );
void OnE3(tuple<e31,...> );
轉化為:
OnEvent(int e, any );
是合理的,因為這樣做可以很好的適應"增加event種類"這一變化。
對"需要增加很多event"或者"event暫時未知"的情況, 是很有用的。
也算是降低了耦合度吧, 因為
>邏輯層也不需要改,只改UI的通知處理即可。
嗯……
相比一些其他的很嚴格的抽象方式, 比如將每個OnE1設置為純虛…… 那簡直是自討苦吃……
一旦增加一個OnEx的純虛, ui代碼就需要改。
如果不是純虛, 或者使用OnEvent(int e, any );就有一個"緩合"的機會, 可以慢慢來~~~
但是, 我有一個猜測, 你看看對不對:
OnEvent(int e, any );
添加這一層, 總工作量不會有絲毫減少, 甚至會增加。
有可能ui端會:
switch (e)
如果e的種類繼續增加, 還可能在ui端繼續轉變為:
ReplyE1(tuple<E11, ... > );
ReplyE2(tuple<E21, ... > );
ReplyE3(tuple<E31, ... > );
再次申明啊, 我覺得OnEvent(int e, any );是有好處的。
logic和ui通過這個通信。
logic內部是否NotifyE1,NotifyE2的形式? UI是否采用RE1,RE2的形式?
這個是完全解耦了。
只是數據格式始終解不了。
>看過一些人直接在MFC的OnXXX里寫一堆邏輯代碼就覺得受不了。
嗯…… 我曾經就寫過讓你受不了的代碼~~~
當然, 現在我也受不了那代碼了……
但是呢, 現在又沒機會去做這種logic,ui分離的事, 只是猜測OnEvent(int e, any );會使得總代碼量增加。
希望能得到你的經驗之談~~~
re: 低耦合模塊間的通信組件:兩個模板 OwnWaterloo 2009-08-23 14:58
光顧著說笑了…… 說點正事。
這樣做算不上"降低耦合"吧?
void OnE1(tuple<e11,...> );
void OnE2(tuple<e21,...> );
void OnE3(tuple<e31,...> );
和:
void OnEvent(int e, any );
的耦合性不是完全一樣么?
log和UI依然必須"協商"每個事件的參數是怎樣的。
只是后一種方式, 將通信的接口納入一個之中, 而不是每產生一個新事件就添加一個, 也就是說, 這個接口可以完全固定下來了, 不會再發生變化。
re: 低耦合模塊間的通信組件:兩個模板 OwnWaterloo 2009-08-23 13:53
@Kevin Lynx
嗯,boost確實有點重……
那么我們拋棄boost::tuple, 使用std::tr1::tuple吧~~~
不過any…… 這可憐的家伙沒被采納…… 得自己實現……
re: 低耦合模塊間的通信組件:兩個模板 OwnWaterloo 2009-08-23 13:35
嘿嘿嘿嘿~~~
設計來、設計去,回到了經典的WndProc模式:
typedef HRESULT (CALLBACK* WndProc)(HWND,UINT,WPARAM,LPARAM);
因為現在有模板這個高級貨, 所以HWND,WPARAM,LPARAM可以塞到一起,變成:
typedef R (*OnNotify)(long type, xxx data);
然后呢, 為了更方便的將各種東西塞入data, lz創造了一個 Param.
試試boost.tuple?
為了讓一個簽名接受不同類型的tuple/Param, 再將它們塞入一個any/void*。
舊瓶新酒~~~
re: 低耦合模塊間的通信組件:兩個模板 OwnWaterloo 2009-08-23 13:27
@megax
同意。 一旦any_cast出錯,就是一個不能逃避,必須得修改掉的錯誤。
相對于void*, any能起到的作用只是開發時的debug?
發布時再改回無檢查的void* ? 還要注意釋放的問題……
re: 一個有趣的小問題 OwnWaterloo 2009-08-20 23:21
@胡友蒙
代碼中只出現了無效地址, 但并沒有解引用。
>而且很多時候都是致命的
這樣做至少在i386上是100%不會出現任何問題, 所以, 不用說得這么嚇人。
re: 一個有趣的小問題 OwnWaterloo 2009-08-20 22:34
(S)(*(sa+100*sizeof(S))).a();
這個表達式有2個小問題, 其他都到位。
由此, 可以給他解釋另一個更經典的……
static_cast<S*>(0)->a();
-_-; ...
template<typename T>
class Obj;
template<typename T>
class Obj_iteator { ... };
template<typename T>
class Obj { ... };
這樣嗎?
re: 強大的bcb OwnWaterloo 2009-08-15 12:50
2和4都是符合標準的, 引用只能綁定到左值, 只有const引用才可以綁定到臨時對象。
FileLoader::RawData FileLoader::GetRawData() const;
const FileLoader::RawData& r = loader.GetRawData();
// 估計不是所希望的, 應該這樣才對:
const FileLoader::RawData v = loader.GetRawData();
void func( Obj &a )
func( Obj() ); // error in ISO C++
void func(const Obj& a);
func( Obj() ); // ok
1. 我只記函數模板中, 局部類可以使用模板參數。
反過來, 還真不記得了……
連同3, 這種使用了生僻模板技術的代碼, 編寫的時候就應該注意按標與各編譯器的支持程度的差異。
@11
> 但是就這個應用來說根本用不到很大的精度
扯談!
那可不可以說“就這個應用根本不需要考慮效率”?
使用多線程(線程池都免了)的效率完全足夠, 并且——我一直強調的——它編碼簡單, 充分利用"OS已經實現的調度機制",而不是自己重復去發明一套弱小的調度功能。
一上來就拋出一句“典型濫用xxx”, 提出一個所謂的解決方案。
典型的“什么事都想靠自己解決”的初級程序員作法。
@11
@11
>Sleep(10); //10毫秒,可以根據需要的精度調整此檢查頻率
嘿嘿, 是不是我需要更高精度的時候, 應該Sleep(5); ???
你看看這個:
999...999 a_long_delay_work.exe
還覺得你那個方法“效率高”?
你想想"可以根據需要的精度調整此檢查頻率"這句話, 當需要的精度要求達到極限時, 比如Sleep(0); 那個while是不是一個"忙等"?
你以為Sleep沒有開銷嗎? 還Sleep(10)呢, 哈哈哈。
你的代碼簡單嗎? 全都是偽代碼。
而且我也說了, OS調度里面, 這些代碼都有, 你老人家何苦要去和它爭呢?
就這Sleep(10) , 還爭什么呢爭……
你這方案, 至少得算出到下一個任務開始前, 應該大致Sleep多久, 它才不算一個忙等。
-------- --------
而且, 這方案還必須是“先得到所有任務”, 再跑這個半死循環, 才可以。
如果需要再跑半死循環的中途, 新建定時任務呢?
這需求很常見, 很多類似“記事簿”的軟件都要提供這功能, 而且是隨時插入新的任務。
顯然, 你必須至少要開2個線程了, 1個用于用戶輸入, 1個用來跑半死循環。
“任務隊列”現在被2線程共享, 又需要加鎖來同步。
這就是我說的, 自己調度會造成編碼復雜的原因, 懂?
別人的方案有何優勢與劣勢?
如此多的方案,它們各自何種情況下是最佳方式?
想過沒? 同學?
不要想都不想——如果Sleep(10)就是你想的結果, 那我真沒什么必要和你繼續說下去了……——就隨便扣個帽子, 你以為能顯示出你很能嗎?
@Stupid ET
這些代碼是你高中寫的?? 牛……
我覺得這思路挺好, 將n個任務分到不同線程, 然后用Sleep的方式通知OS。
誰知道OS里面會不會有:
“來一個排序, 以一個小的粒度檢查時間來運行要運行的”線程
這種調度算法呢?
誰知道OS會不會比ls某位的算法更差呢?
誰知道windows下的創建線程開銷會比ls某位的算法高呢?
這些都不知道, 要測也不方便。
但是, 編碼簡單很多~~~ 同時線程間的同步也很方便處理。
KISS~~~
@OwnWaterloo
哦, 原來是個backward compatibility函數……
> Sleep(InputHandle()+2000); // 主線程暫停等待其他線程運行完畢
嚴格給的說, 要用 WaitForMultipleObjects。
如果人品非常差, 延遲2秒還是有主線程先結束的可能, 因為調度順序是未知的。
> 因為調度未知
從CreateThread開始, 到次線程Sleep 之間會有未知時間的間隔。
所以, 傳給次線程的, 不應該是delay, 而是awake_time。
次線程在Sleep前一刻, 根據awake_time和current_time, 計算Sleep多久。
這樣, 精度就不受CreateThread,到Sleep之間那段未知時間的影響。
如果精度還要提高, 可以用WaitableTimer。
> CreateThread
在vc上用_beginthreadex代替。 dev c++如果是用的mingw, 也有這個函數。
最后一點………… 其實偷懶的話去查AT的用法 ……
run -> cmd -> at /?
直接寫個bat文件:
at xxxx notepad
at yyyy calc
....
而不用寫一個配置文件, 然后用一個程序去讀, 再執行……
功能差不多, 精度可能低一些。
re: FOX TOOLKIT 學習 - 文本顯示 OwnWaterloo 2009-06-27 11:46
@visualfc
原來是要處理utf8...
我指的是
c89 stdlib.h
mbstowcs
wcstombs
c99 wchar.h
mbsrtowcs
wcsrtombs
轉換跟locale有關, 標準只保證有"C"和""兩種locale存在。
其他的也是跟實現相關。這樣的話,上面4個函數的可移植優勢就不大了。
同時msvc的crt還不支持utf8 ...
那就用iconv吧。。。 挺好的一個庫。
為什么一定要找基于fox的方案呢?
另外,FXString 存放的總是utf8?
要將其顯示在控件上?
將 utf8 轉為 utf16 再用 xxxxW 函數應該就可以顯示了。
應該不用轉成 gbk 然后用 xxxxA 函數。
re: FOX TOOLKIT 學習 - 文本顯示 OwnWaterloo 2009-06-25 10:54
>>在Windows平臺上我使用了MultiByteToWideChar來實現代碼頁轉換,如果誰能有基于FOX的解決方案,歡迎進行指點和幫助。
有基于C標準庫的方案。
re: 查看源文件預處理結果 OwnWaterloo 2009-06-08 15:27
@zhichyu
應該跟源文件行號有關, 具體我不清楚
re: 技術回歸01-Windows內存分配工具 OwnWaterloo 2009-06-04 12:04
@萬連文
微軟的哪? MFC?
上面的命令行 cl /MD 已經告訴編譯器鏈接到動態庫了。
vc6不支持是因為它只有靜態庫。 crt的動態庫是跟.net那一套東西一起出來的。
re: 技術回歸01-Windows內存分配工具 OwnWaterloo 2009-06-04 10:32
sorry…… 不小心提交了2次 ……
我自己刪掉一個 ……
re: 技術回歸01-Windows內存分配工具 OwnWaterloo 2009-06-04 10:32
1
#include <stddef.h>
2
#include <stdlib.h>
3
#include <stdio.h>
4
#include <vector>
5
6
#include <stdexcept>
7
8
9
#if defined(_MSC_VER) && _MSC_VER<1400
10
#include <new.h>
11
namespace std
{ using ::set_new_handler; using ::new_handler; }
12
#else
13
#include <new>
14
#endif
15
16
17
void* allocate(size_t size)
{
18
if (size==0) size = 1;
19
for (void* p=0;;)
{
20
p = malloc(size);
21
if (p)
{
22
printf("allocate %p\n",p);
23
return p;
24
}
25
std::new_handler handler = std::set_new_handler(0);
26
std::set_new_handler(handler);
27
if (handler)
28
handler();
29
else
30
throw std::bad_alloc();
31
}
32
}
33
34
void deallocate(void* ptr)
{
35
printf("deallocate %p\n",ptr);
36
free(ptr);
37
}
38
39
void* operator new(size_t size)
{ return allocate(size); }
40
void* operator new[](size_t size)
{ return allocate(size); }
41
void operator delete(void* ptr)
{ deallocate(ptr); }
42
43
class C
{
44
static int count;
45
public:
46
static bool fail;
47
C()
{
48
if (fail)
49
throw std::exception();
50
printf("C::C(),%d\n",++count);
51
}
52
~C()
{
53
printf("C::~C(),%d\n",count--);
54
}
55
C(const C& )
{
56
printf("C::(const C&),%d\n",++count);
57
}
58
59
60
//void* operator new(size_t,void* place) { return place; }
61
void* operator new(size_t size)
{ return allocate(size); }
62
void* operator new[](size_t size)
{ return allocate(size); }
63
void operator delete(void* ptr)
{ deallocate(ptr); }
64
};
65
bool C::fail;
66
int C::count;
67
68
struct S
{
69
static bool fail;
70
S()
{
71
if (fail)
72
throw std::exception();
73
printf("construct\n");
74
}
75
~S()
{
76
printf("destroy\n");
77
}
78
};
79
bool S::fail;
80
81
void test_class(int dim)
{
82
if (dim<=0)
83
return;
84
C::fail = dim==4;
85
C* arr = new C[dim];
86
delete[] arr;
87
}
88
89
90
void test_global(int dim)
{
91
if (dim<=0)
92
return;
93
S::fail = dim==4;
94
S* arr = new S[dim];
95
delete[] arr;
96
}
97
98
int main()
{
99
using namespace std;
100
int dim = 0;
101
for (printf("input dim: ");scanf("%d",&dim)==1;printf("input dim: "))
102
{
103
try
{
104
test_class(dim);
105
}
106
catch (std::exception& )
{
107
printf(" ---- catch an exception ----\n");
108
}
109
try
{
110
test_global(dim);
111
}
112
catch (std::exception& )
{
113
printf(" ---- catch an exception ----\n");
114
}
115
}
116
}
117
有兩個底層分配函數allocate和deallocate,它們使用malloc和free。
用這兩個函數實現全局的3個op new,op new[], op delete,沒有op delete[]
還用這兩個函數實現了C的3個op new,op new[], op delete,同樣沒有op delete[]
用如下參數編譯
cl /EHsc /MD /analyze /W3
你看看結果吧。
我用vc8、9測過(vc6不支持動態crt庫,vc10我沒裝)。
反正兩處delete[] arr;都沒有調用 op delete。
它們調用那個全局的,沒有被重寫的op delete[]。
如果靜態鏈接,該全局默認的op delete[]會被inline, 再調用該編譯單元中定義的op delete。
如果動態鏈接,op delete[]不會被inline,會調用crt庫中提供的op delete。
總之,這兩處delete[] arr;都沒有調用deallocate。
當然, 你可以說你只靜態鏈接到crt庫。
也可以說你的allocate和deallocate底層實現絕對會一直保持與vc提供的crt兼容。
但是,你的代碼的用戶了解么?
難道你打算在文檔中寫“使用我的庫的代碼者,使用的crt庫必須滿足XXX要求,必須自己測試YYY”,只是為了你自己可以少寫一個 op delete[]?
這不是程序庫開發者的態度。
還有兩個小問題。
C* pc = static_cast<C*>(malloc(sizeof(*pc));
new (pc) C; // 編譯錯誤
C* pc2 = new (std::nothrow) C; // 編譯錯誤
當然, 你還是可以說你絕對不會用這種東西, 你是實用主義嘛。
但是你的庫的使用者呢?
“出發點只是想找到一個經過驗證的(大的、成功的產品使用過的)簡便的工具”
你覺得這可以說明該產品中的每個細節都是無可挑剔的么?
越是大的產品,測試越不容易,更不容易暴露其中的問題,同時也許忽悠客戶也更容易。
確實沒有任何事物都是完美的,但不能連追求完美的心都舍棄了。
同時,從實用角度出發,讓該庫變得更完美,所付出的代價非常小,“按規則”辦事就可以了,10來行代碼的事,何樂而不為?
規則可以見《EffCpp》或者《C++CodingStandard》。
re: 技術回歸01-Windows內存分配工具 OwnWaterloo 2009-06-03 21:30
@萬連文
某某牛庫是哪個庫?
其實跟有沒有庫這樣做沒關系,跟該庫牛不牛也沒什么關系。
不能跟著別人錯。
底層實現是HeapXXX?
其實跟底層實現到底是什么沒關系。
C++標準沒要求底層實現怎么做, 但是要求重載operator new必須有其對應形式的operator delete重載。
跟測不測試也沒關系。
一次不帶TT不會懷上不等于次次都不會懷上。
一個編譯器上測試成功,不等于每個編譯器都能測試成功。
在某個編譯器上能測試通過,并不能證明或證偽。
編寫operator new/delete要遵守一些規范。
HeapAlloc能否處理 size=0?
HeapAlloc分配失敗時的new_hanlder處理?
對其他形式new的隱藏?
"重載"(而不是覆蓋全局標準)op new時,如果不提供相應形式的op delete,是否也能正確工作?
與其在不同平臺,不同編譯器,甚至是相同編譯器的不同版本下進行測試,不如一開始就按照標準形式編寫。
re: 技術回歸01-Windows內存分配工具 OwnWaterloo 2009-06-03 16:51
operator delete[]呢?
re: delete operator OwnWaterloo 2009-05-10 21:46
re: delete operator OwnWaterloo 2009-05-10 21:42
這樣寫是不正確的。
new操作符的含義是:
1. 調用相應的operator new分配內存
2. 在該內存上構造對象
delete 操作符執行相反的工作。
1. 調用對象的析構函數
2. 調用operator delete釋放內存。
如果只調用operator delete, 對象析構函數將得不到調用。
re: 最簡單的foreach實現(VC & GCC) OwnWaterloo 2009-05-08 12:46
同時…… 非常不明白 ……
為什么很多C++程序員(甚至是許多老手)都喜歡使用下劃線開頭的標識符……
這是個非常不好的習慣……
re: 最簡單的foreach實現(VC & GCC) OwnWaterloo 2009-05-08 12:42
-------- -------- 引 -------- --------
這里有一個特殊的考慮,就是container有可能是一個臨時對象,或者是某個函數的返回值。為了不對容器進行復制,利用了一個不太為人所知的C++特性,就是臨時變量在存在引用時,生命期會由引用變量決定。這樣保證在進行循環時始終有效。
-------- -------- 引 -------- --------
函數返回值就是臨時對象的一種吧?
這個特性更準確描述應該是:
const 引用可以綁定到一個臨時對象上,
臨時對象的生命周期將延長至const引用超出作用域。
臨時對象原本的生命周期僅到產生臨時對象的完整表達式結束。
-------- -------- 分割線 -------- --------
是否可以考慮這樣修改?
#define foreach(var, container) \
{ \
/... \
}
——1是可以避免臨時對象的生命周期被延長到不需要的地方
——2是可以避免一個bug:
#define RANDOM_VAR(name, line) name ## line
這個宏不會以你想想中的樣子工作。
至少要改成:
#define RANDOM_VAR(name, line) RANDOM_VAR_(name,line)
// 交給另一個宏
#define RANDOM_VAR_(name,line) name##line
// 才能啟動rescan機制,將__LINE__展開
——3. 如果讓foreach_helper有一個到container的const引用, 也就不需要單獨的RANDOM_VAR去提升container的生命周期了。
Run-Time Check Failure #2 - Stack around the variable 'version' was corrupted。
這個錯誤信息描述不太準確。
其意思是,msvc在debug下為棧上自動變量周圍分配了一些保護空間。
如果發生棧溢出, 就會寫到保護空間上去。
這樣, 棧溢出就能被檢查出來, 并且告訴程序員, 某個變量附近的棧空間被破壞(腐壞?)了。
所以要重現這個錯誤只要這樣:
int a[1212];
a[1986] = 0;
或者, 樓主的代碼與下面更類似:
int i;
(&i)[ 1 ] = 0; // 取i的地址, 將其作為數組傳遞給fread。
// 但其實這個“數組”, 只有一個元素。 也會發生溢出
要修改, 要么一次只讀取一個version。
要么將version改到合適大小(10就能保證一定不溢出嗎?)
re: WCHAR我不再懼怕了 OwnWaterloo 2009-04-28 22:40
@shongbee2
#include <locale>
wcout<<L"漢字";
assert( !wcout );
wcout.imbue(locale("chs"));
wcout.clear();
wcout<<L"漢字";
re: 過來開個坑 OwnWaterloo 2009-04-25 16:10
終于游說成功 ……
哪不方便? 網易我沒寫過……
不過不支持評論rss或者通知比較不爽。。。
@vitacy
1. C標準對默認實際參數提升規則有明確規定。
也就是說, 帶有可變長參數列表的函數, 絕對不會接受到char類型的實際參數。
2. C標準對va_arg是否自動對齊沒有任何說明。
你說的va_arg(va_list,type)是自動對齊, 只是在你的編譯器上。
并不是所有編譯器都能自動幫你完成這個工作。
在所有C實現上, 能保證第1點, 但不能保證第2點。
依賴于第2點, 代碼就依賴于特定編譯器。
你說va_arg(ap,type)是自動對齊, 證明你有研究過。
喜歡作這些研究的, 都是聰明的家伙。
但聰明的家伙總喜歡不按規矩辦事。
在gcc (GCC) 3.4.2 (mingw-special)中, type使用char, 會得到嚴重的警告:
`char' is promoted to `int' when passed through `...'
(so you should pass `int' not `char' to `va_arg')
note: if this code is reached, the program will abort
它會直接掛掉你的程序,來約束你必須按規矩辦事。
re: 查看源文件預處理結果 OwnWaterloo 2009-04-21 14:45
將需要處理掉的那部分單獨copy出來可以嗎?
re: std::endl 是什么? OwnWaterloo 2009-04-18 20:58
class slt_like_ostream {
slt_like_ostream&
operator<<(std::ios_base& (*pf)(std::ios_base& );
template< class C, class T >
slt_like_ostream&
operator<<(std::basic_ios< C,T>& (*pf)(std::basic_ios< C, T>&);
template< class C, class T >
operator<<
(std::basic_ostream< C,T>& (*pf)(std::basic_ostream< C,T>&);
};
這是stl對ostream的規范。
如果不實現這些規范, 不能與stl的其他組件(如std::endl)合作也是理所當然的。
re: 自己實現的memcpy OwnWaterloo 2009-04-18 20:27
還發現一個問題……
void* my_memcpy(void *dst, /* const */ void* src, int size);
re: 自己實現的memcpy OwnWaterloo 2009-04-18 19:08
re: 自己實現的memcpy OwnWaterloo 2009-04-18 15:30
沒有考慮內存對齊。
re: ACM模板之—循環隊列(模板類) OwnWaterloo 2009-04-03 18:43
指針算術
re: ACM模板之—循環隊列(模板類) OwnWaterloo 2009-04-03 11:58
簡單的說, 假設你想查看前1212個元素,應該寫 :
test.element, 1212。
re: ACM模板之—循環隊列(模板類) OwnWaterloo 2009-04-03 11:55
T arr[sz];
watch中寫arr。 watch會將arr認為是數組, 并且可以讓你展開,查看特定元素。
T* p;
watch中寫 p。 watch會將p認為是指針, 只能展開1項, 查看其值。
watch中寫 p,n。 watch將認為p是一個數組的首地址, 并為你展開前n項。
re: istringstream類研究 OwnWaterloo 2009-03-25 18:48
@abilitytao
那直接就有 iostream streambuf exception stdexcept 這些文件咯?
它們的文件名都超過8個字符。
我這里沒有…… 所以我懷疑是vc6 for dos……
我也有vs2008 …… 不過還有固執的人在使用vc6 …… 所以盡可能的提供支持……
re: istringstream類研究 OwnWaterloo 2009-03-25 13:20
@abilitytao
sorry, 剛才語氣有點過激。
希望樓主能解答我的問題, 再次感謝~~
re: istringstream類研究 OwnWaterloo 2009-03-25 12:31
@abilitytao
我還不知道iostream屬于標準庫嗎?
我只是想問下樓主的vc6的版本?
Microsoft Visual Studio\VC98\Include下的文件是大寫還是小寫?
有沒有8字符限制?
謝謝~
re: istringstream類研究 OwnWaterloo 2009-03-24 23:46
以上程序在vc6.0上運行正常?
我這里的vc6, 會報很多頭文件缺失。
比如iostream 會缺少streambuf stdexcept exception
要自己寫這3個文件, 分別再include STREAMBF STDXCEPT XCEPTION
總之, 我這里的vc6的include中的頭文件, 名字全是大寫,而且都不超過8個字符。
我懷疑我用的是不是vc6 for dos 。。。。
re: 對malloc的返回值應該如何轉型 OwnWaterloo 2009-03-17 22:56
@C++ Beginner
如果一個用戶自定義類型C,
有一個可以通過單個類型為T的參數進行調用的構造函數,
那么,該構造函數就定義了一個T到C的轉換。
如果該構造函數是explicit的,T到C的轉換是顯式轉換。
如果該構造函數不是explicit,T到C的轉換是隱式轉換。
例如:
class string {
char* content_;
explicit string(const char* source,int length=-1)
:content_(0)
{
if (length==-1)
length = static_cast<int>(strlen(source));
content_ = new char[length+1];
strcpy(source,content_);
}
};
這個構造函數可以通過單個參數調用(第2個參數有默認值),所以這個構造函數定義了一個 const char* 到 string 的轉換。
如果有explicit,那么該轉換必須是顯式轉換:
string s = static_cast<string>("hello");
如果沒有explict,該轉換可以是隱式轉換:
string s = "hello";
上面說錯了,這種轉換確實會調用構造函數。