<http://homepage2.nifty.com/magicant/programmingmemo/genericsjavavscs.html>
C# は型引数の数だけクラスを展開し、
そのバイトコードを生成するので、実行時に型引数の情報が残る。
Java は型引数の一致をコンパイル時に判定するが、
バイトコートは型引数によらない(ワイルドカードの)クラスだけなので、
実行時に型引数の情報が残らない。
(Java のジェネリクスは、ダウンキャストを自動化するだけ)
<http://www.google.com/search?q=C%2B%2B+for+Java+Programmers>
これらのドキュメントはだいたい、
Java プログラマが C++ で書けるようになることを目標にしている。
書くのは、大体、逐語訳で書ける。
C++の方が多くの構文を持っているので。
# interface がないとかデフォルトが値渡しだとか
# 無名クラスができないとか
しかし、Java プログラマが C++ を読めるようになるのは、
そこからかなり遠いような気がする。
template specialization のパターンマッチは、
類推も効かないし、翻訳するにもけっこう複雑な翻訳になる。
あと typedef はないので、つい頭がそこに行かない。
型名と変数名が混乱して、
初期化引数つき変数定義と、関数呼び出しの区別が付きにくい。
あと演算子オーバーロードと暗黙の型変換のコンボが強すぎる。
結局、C++ をネイティブなみに読み書きするには、
Java を忘れなければならない。
Java の継承は C++ の public 継承。つねに is-a 関係が成立する。
#include <iostream> class Root { private: static const int priv = 100; protected: static const int prot = 20; public: static const int pub = 3; public: int get() { return priv + prot + pub; } }; class SubPub : public Root { public: int get() { return pub + prot; } }; class SubPriv : private Root // overrides all the members as private {}; class SubPrivPub : public SubPriv { public: //int get() { return pub; } int get() { return -1; } }; int main() { SubPub s1; std::cout << s1.get() << std::endl; // SubPriv s2; // std::cout << s2.get() << std::endl; // the private inherited class is NOT a subclass of the Root return 0; }参考 C++ Annotations
<http://www.intel.com/cd/software/products/asmo-na/eng/compilers/clin/219856.htm>
Intel C++ Compiler for Linux*Free Non-commercial Unsupported Compiler
icc は C++ のソースのみ、 C++ のライブラリとのリンクする。
icpc は いつも(Cのソースでも) C++ のライブラリとリンクする。
#include <iostream> class Complex { private: const double re; const double im; public: Complex(double r = 0.0, double i = 0.0) : re(r), im(i) { std::cout << "constructor: " << *this << std::endl; } Complex(const Complex& c) : re(c.re), im(c.im) { std::cout << "copy constructor: " << *this << std::endl; } ~Complex() {} Complex operator=(const Complex& c) // field が immutable だと、デフォルトの代入はできない { return Complex(c); } friend Complex operator+(const Complex&, const Complex&); friend std::ostream& operator<<(std::ostream& s, const Complex&); }; Complex operator+(const Complex& c1, const Complex& c2) // const .. & がないと { // copy constructor が呼ばれる return Complex(c1.re + c2.re, c1.im + c2.im); } std::ostream& operator<<(std::ostream& s, const Complex& c) { return s << "(" << c.re << ", " << c.im << ")@" << &c; } template<class T> T add(const T& a, const T& b) { return a + b; } int main() { double x = add(10, 20); std::cout << x << std::endl; Complex c1(10.0, -10.0); Complex c2(-2); std::cout << "add<>()" << std::endl; Complex c3(add(c1, c2)); // same to add<Complex>(c1, c2) std::cout << c3 << std::endl << std::endl; std::cout << "operator+()" << std::endl; Complex c4(c1 + c3); std::cout << c4 << std::endl << std::endl; std::cout << "operator+(), substitution" << std::endl; Complex c5 = c2 + c4; Complex c6; c6 = c5; std::cout << c5 << std::endl << std::endl; c6 = 0; add<Complex>(1, 2); return 0; }
30
constructor: (10, -10)@0x22ccb0
constructor: (-2, 0)@0x22cca0
add<>()
constructor: (8, -10)@0x22cc90
(8, -10)@0x22cc90
operator+()
constructor: (18, -20)@0x22cc80
(18, -20)@0x22cc80
operator+(), substitution
constructor: (16, -20)@0x22cc70
constructor: (0, 0)@0x22cc60
copy constructor: (16, -20)@0x22cc50
(16, -20)@0x22cc70
constructor: (0, 0)@0x22cc30
copy constructor: (0, 0)@0x22cc40
constructor: (2, 0)@0x22cc10
constructor: (1, 0)@0x22cc00
constructor: (3, 0)@0x22cc20
operator+を外で2項関数として定義する理由は、
第一引数に関して暗黙の型変換を有効にするため。
ようするに、
Complex(0,1)+1 も
1+Complex(0,1) も書けるようにするため。
上の方はどうでもよくて、面白いのは最後のところ。
引数のデフォルト値と演算子オーバーロードができると、こんなこともできるんですね...
<http://www.kmonos.net/alang/boost/>
STL の次は Boost。
STLもまだまだ勉強中だけど...
+STLのページ
+Standard Template Library プログラミング on the Web
+SGI - STL Programmer's Guide
boost::property_mapに書かれている concept というのは、Java の interface に近いのかな。
Solaris の CC /usr/ucb/cc は K&R らしい。
K&R
int sendf(va_alist) va_dcl { static char buf[10240]; /* xxx, enough? */ SOCKET s; const char *fmt; va_list args; va_start( args ); s = va_arg( args, SOCKET ); fmt = va_arg( args, char * );
int sendf(SOCKET s, const char *fmt...) { static char buf[10240]; /* xxx, enough? */ va_list args; va_start( args, fmt );
<http://www.bdsoft.com/tools/stlfilt.html>
C++ コンパイラが出すエラーメッセージを解読してくれる
という、ジョークなのかどうかよく分からないプログラム。
<http://www.cs.brown.edu/courses/cs123/javatoc.shtml>
<http://winnie.kuis.kyoto-u.ac.jp/~yoshii/cpp.html>
後藤さんの共同研究者、吉井さんによる。