C++FAQ

Monday, January 30, 2006

 

'this'指標是什麼?

Q: 'this'指標是什麼?

A: 一般人很容易誤以為'this'指標是一個class或struct的隱函成員。實際上它是non-static member function的隱藏參數。當你宣告一個function時,Compiler會自動在前面加上這個參數到你function的prototype中。這個參數的形別是根據你在如何宣告你的function。根據C++標準,9.3.2.1中所提到:

在nonstatic member function中,關鍵字'this'是一個non-lvalue expression,它的值是目前呼叫此function的物件之記憶體位置。若此function是宣告在class X中,則這個'this'的形別就是X*。若這個member function是被宣告為const,則此'this'的形別就是const X*,如果這個function宣告為volatile,則這個'this'的形別就是volatile X*,如果這個function被宣告為const volatile,則此'this'的形別就是const volatile X*。

比如說:
class T
{
public:
void foo(int a);
int goo() const;
};
實際上是:
class T
{
public:
void foo(T* this , int a);
int goo(const T* this) const;
};
Static member function不會有這個額外的參數。你不能使用non-static member function做為thread function,即使它有正確的prototype。(One consequence is that you cannot use a non-static member function as a thread function even if it has the correct prototype,不太確定對不對)

比如:
UINT ThreadFunction(LPVOID param);

因為上述的理由,會變成:
UINT ThreadFunction(T* this, LPVOID param);



Sunday, January 29, 2006

 

如何把數值形別變成字串形別?

Q: 如何把數值形別變成字串形別?

A:

舊時 C 的做法 (已不被建議使用):
char c[10]; // simply large enough - don't forget the
// extra byte needed for the trailing '\0'
int i = 1234;
sprintf(c, "%d", i);
可以在如MSDN查到'sprintf()'的細節。

使用 'CString':
int i = 1234;
CString cs;
cs.Format("%d", i);
使用的方式類似於'sprintf()'。可以在MSDN查到更多細節。

注意: 如果指定的specifiers (也就是上面'%d'的部份)與實際傳入的參數不同,將會造成不可預期的結果,'sprintf()'與'CString::Format()'都要小心這種錯誤。


C++的做法

下面的這個例子告訴你如何使用標準的C++ class來做:

#include <string>
#include <sstream>
#include <iostream>

template <class T>
std::string to_string(T t, std::ios_base & (*f)(std::ios_base&))

{
std::ostringstream oss;
oss << f << t;

return oss.str();
}

int main()

{
// the second parameter of to_string() should be one of
// std::hex, std::dec or std::oct
std::cout<<to_string<long>(123456, std::hex)<<std::endl;

std::cout<<to_string<long>(123456, std::oct)<<std::endl;

return 0;
}

/* output:
1e240
361100
*/



這個方法不只非常漂亮,而且是type safe的,因為Compiler在compile time時根據運算元(operand)的形別選擇適當的'std::ostringstream::operator << ()'。

另外: (下面這段不知道怎麼翻)

There is a new method with 'boost::format', which combines the advantages of printf with the type-safety and extensibility of streams.

One of the advantages (as with printf) is you can store the entire format string as a template (not a C++ template). This is better for internationalisation (making string tables), as well as the fact that even just using a local string table can significantly reduce the code-size.

 

有哪些字串的形別(type)?

Q: 有哪些字串的形別(type)?

A:

 

字串

  1. 有哪些字串的形別(type)?
  2. '\n'與'\r\n'的差異在哪?
  3. 如何在非MFC的程式中使用'CString'?
  4. 如何給定或比較字串?
  5. 'CString'與'std::string'的差異在哪?
  6. 如何在'CString'與'std::string'之間轉換?
  7. 如何把數值形別變成字串形別?
  8. 如何把字串形別變成數值形別?

 

C++ Headers是什麼?

Q: 標準之前(pre-standard)的傳統(traditional) C++ header是怎麼回事?

A: 傳統的C++ header定義classes, values, macros, 以及function,並且以.h做為副檔名(extension)。包括了非標準的STL header,也是以.h做為副檔名 (iostream.h, fstream.h, vector.h, ... 諸如此類),以及過去C的header也是 (stdlib.h, stdio.h, ... 諸如此類)。標準之前的header具有全域的 namespace (Pre-standard headers have all the code in the global namespace,不太確定怎麼翻這句。)

Q: C++的標準header是怎麼回事?

A: 就是那些已經被列入了C++標準的headers。


Q: 我怎麼知道某個header是不是C++的標準header?

A: 命名的方式和傳統的header命名是一樣的,只是去掉了'.h'的副檔名。比如說,'fstream.h'變成了'fstream','memory.h'變成了'memory',諸如此類。


Q: 'iostream.h'是怎麼回事?

A: 這個'iostream.h'從未成為官方的C++標準,這代表任何實作iostream.h的C++ compiler,可以依著它想要的方式去做,而這樣的compiler仍舊會被視為與C++標準相容的。無論如何,C++標準有把input/output library列入其中。


Q: 傳統ANSI C的標準header是怎麼回事?

A: 傳統的ANSI C標準header是以'c'字母為開頭。因此,如'stdio.h'就變成了'cstdio','stdlib.h'就變成了'cstdlib','math.h'就變成了'cmath','time.h'就變成了'ctime',依此類推。以下是完整的列表:




Q: 哪一些是C++標準header?

A: 以下是列表:

語言支援:
動態記憶體管理: <new>
偵錯:
一般公用:
字串:
本地化:
容器:
演算法:
數值:
輸入/輸出:

Q: 我仍舊可以使用舊版的C header嗎 (stdlib.h, stdio.h, etc.)?

A: 所有與C++相容的compiler都支援上述那18個以'.h'做為結尾的header檔,即使它們是不被建議使用的 (stdlib.h, stdio.h, etc.)。這些*.h的 C header檔都是global namespace。使用這些版本的C header仍舊被視為具有可攜性的 (portability),但它有可能與未來的標準不相容。無論如何,這些header在未來不太完全可能被官方標準移除。


Q: 我仍舊可以使用那些非標準的,以'.h'做為副檔名版本的STL header嗎 (iostream.h, fstream.h, vector.h, etc.) ?

A: 這樣的STL header從未成為C++官方標準,大部份的C++ Compiler支援這樣非標準的header,也有些過時的Compiler(如Turbo C++)只支援這樣非標準的寫法。有些更新穎的Compiler,如VC++ 7.1已經不再支援這樣非標準的寫法。除非你必須要使用這些過時的Compiler,否則的話最好是使用標準的寫法 (<iostream>, <fstream>, <vector>, etc.)。使用*.h的寫法不好。

另外:

在某些Compiler上,你可以發現它同時有'iostream'以及'iostream.h'。如上所述,在include 'iostream'時那些成員(members)是在std namespace,而'iostream.h'是在global namespace。這可能會在某些時後造成混淆(ambiguities),namespace的設計就是為了避免這樣的情況。這也是建議不要使用*.h的原因之一。


 

到底ntohl()與htonl()做了什麼?

Q: 到底ntohl()與htonl()做了什麼?
A: 'ntohl()'與'htonl()'是四個相關function中的其中二個,另外二個是'ntohs()'與'htons()',以下是Linux manual中的解釋:


這四個function在host byte order與network byte order之間做轉換。當二者的byte order不同時,則使用這些function會造成endian-ness的改變。當二者的byte ordre一樣時,則不會有任何的改變。因此,當你只是單純想要做endian-ness的轉換(無關乎平台),則不該使用這些function。這一篇FAQ告訴你如何做無關乎平台的endian-ness轉換。

Special notes:

 

我如何轉換Big-Endian與Little-Endian的格式?

Q: 我如何轉換Big-Endian與Little-Endian的格式?
A:
轉換的動作是可逆的 (Big-Endian <-> Little-Endian),下面這個例子可以用來轉換unsigned data types.

inline void endian_swap(unsigned short& x)
{
x = (x>>8) |
(x<<8);
}

inline void endian_swap(unsigned int& x)
{
x = (x>>24) |
((x<<8) & 0x00FF0000) |
((x>>8) & 0x0000FF00) |
(x<<24);
}

// __int64 for MSVC, "long long" for gcc
inline void endian_swap(unsigned __int64& x)
{
x = (x>>56) |
((x<<40) & 0x00FF000000000000) |
((x<<24) & 0x0000FF0000000000) |
((x<<8) & 0x000000FF00000000) |
((x>>8) & 0x00000000FF000000) |
((x>>24) & 0x0000000000FF0000) |
((x>>40) & 0x000000000000FF00) |
(x<<56);
}


Q: 為何不直接使用ntohl()與htonl()就好了?
A: 這二個function:


更多的資訊,請看到底ntohl()與htonl()做了什麼?

 

General

  1. C++有什麼推薦的好書?
  2. 我如何轉換Big-Endian與Little-Endian的格式?
  3. 到底ntohl()與htonl()做了什麼?
  4. 如何宣告與使用二維陣列?
  5. 不同的數字表示法差異何在?
  6. 浮點數是怎麼表示的?
  7. 如何處理references?
  8. 物件導向設計(OOD)的概念精神是什麼?
  9. Inline Function與Macros的差異何在?
  10. 'this'指標是什麼?
  11. 傳遞參數到functions有哪幾種不同的方法?
  12. C++ Headers是什麼?
  13. 一個class有什麼已經被隱涵定義好的成員?

 

C++ FAQ Sections


 

C++ FAQ

The purpose I made this Blog is that when I see the C++ FAQ in CodeGuru, I think it is very useful for any newbie who is studying C++, so I want to translate it into Chinese. I am a C++ newbie too, I will try to do my best to translate the FAQ, and any comment is appreciated.

Archives

January 2006   February 2006  

This page is powered by Blogger. Isn't yours?