C++このように使いたい(五)
10408 ワード
上一篇は【C with Class】の文法の第1部を述べて、以下は第2部に続きます:
第二部分:プロセス向けのプログラミングスタイル
何がプロセスに向いているのか分からないなら、あなたは絶対にCプログラマーではないと思います.実は私は个人的にプロセスに向いて、モジュール式のCプログラミングの风格は最もすばらしい范式だと感じて、ふだん私达が出会った大多数の问题のため、すべてこのような范式で解决することができて、その上设计はかなり简洁で明快で、决して泥を引きずって水を持っていないで、逆にひっきりなしに対象の型に向かって本当にあなたを问题の本质からますます远く离れさせます.プロセスのパターンにどんなに慣れていても、C++環境ではいくつかの違いがあります.
1.参照について:
引用は現代のプログラミング言語によくある概念であり、自然にC++が導入した新しい言語特性でもあり、C++でよく使われる重要な内容である.しかし、私はツッコミを入れないわけにはいきません.他のオペレータを使ってはいけませんか.Cを使って開発することに慣れている友人たちは、c++に現れる&記号を見て、ぼんやりするかもしれません.C言語ではこの記号はアドレスを取る記号を表していますが、C++では引用を表すために使われているので、多くの混乱した書き方が発生しています.
#includeint main(void)
{ int a = 0;//&a = 0x0012ff60
int *p = &*(int*)0x0012ff60;
printf("The value is: %d", *p);
return 0;
}
私は本当に貼りたくなくて、見るたびに吐き気がして、、とにかくこれはとても奇抜な現象で、針という究極の武器がある言語の中で引用を導入して、本当に混乱しています.私の提案は次のとおりです.
a)もしあなたがC++プログラマーなら、あなたの引用を使ってください.ポインタをいじってはいけません.
b)逆にあなたはCプログラマーですから、自愛して、引用から離れてください!!少なくともC with Classでは使用禁止です.
2.newとdeleteの使用上の注意
これまでnewとdeleteオペレータは私が受け入れた唯一のC++の中のもので、相手に向かうために受け入れざるを得なかった以上、彼らをよく使わなければなりません.
新用法:
1.単一変数アドレス空間を開く
1)int *a = new int;//格納配列の格納空間を開き、その格納空間を指すアドレスを返す.int*a=new intは、intタイプのアドレスを整数ポインタaに付与ものである.
2)int *a = new int(5);//作用は同じですが、同時に整数を5に割り当てます.
2.アレイスペースを開く
int *a = new int[100];//サイズ100の整数配列空間を開く
deleteの使い方:
1. delete a;//個々のintのスペースを解放する
2. delete [] a;//int配列空間の解放
deleteとdelete[]の違いに注意してください.C++は、newで割り当てられた単一オブジェクトのメモリスペースを回収するときにdelete、new[]で割り当てられたオブジェクトのセットのメモリスペースを回収するときにdelete[]を使用することを教えてくれます.new[]とdelete[]については、(1)基本データ型の割り当てと回収空間;(2)カスタムタイプにスペースを割り当て、回収します.
次の手順を参照してください.
皆さんは自分でこのプログラムを実行して、delete p 1とdelete[]p 1の異なる結果を見て、私はここで実行結果を貼りません.実行結果からdelete p 1は空間を回収する過程でp 1[0]というオブジェクトだけが構造関数を呼び出し,p 1[1]、p 1[2]などの他のオブジェクトは自身の構造関数を呼び出していないことが問題であることが分かる.delete[]を使用すると、スペースを回収する前にすべてのオブジェクトが最初に独自の構造関数を呼び出します.基本タイプのオブジェクトには構造関数がないので、基本タイプからなる配列空間を回収するにはdeleteとdelete[]を使用することができるはずです.ただし、クラスオブジェクト配列ではdelete[]しか使用できません.newの単一オブジェクトの場合、delete[]でスペースを回収することはできません.
したがって、簡単な使用原則は、newとdelete、new[]とdelete[]が対応して使用されることです.
3.関数パラメータのデフォルト
そう、多くのCプログラマーは、C++が関数パラメータにデフォルト値を割り当てることができることをとっくに知っていて、呼び出し時に指定しない場合はデフォルト値を使用します.私はこの特性が本当にとても悪くないと思って、APIを设计するために极めて便利を提供することができて、しかしCの中ではありませんて、もしあなたの强迫症が特に深刻ではありませんならば、私はこの特性を受け入れることができると思って、もし不幸にも铳に当たっても心配しないで、実はCを使って私达もこの特性をシミュレートすることができて、最も鋭いMacroを使います!!
具体的なやり方は以下の通りです.
はい、確かに複雑で、実際には適切に簡略化することができますが、もしあなたが本当にライブラリを設計したいなら、上の完全な書き方は本当に素晴らしいですよ.そして移植性が高いですね.もちろん、これは私が考えたものではありません.元のリンクはここにあります.
http://stackoverflow.com/questions/3046889/optional-parameters-with-c-macros
4.inline関数
以前のCはinlineというものはありませんでしたが、頻繁に使う小さな関数については、マクロ関数と書くことが多く、関数展開のオーバーヘッドを低減することができます.しかしC++はあり、多くのコンパイラもCにこの拡張を加えた.例えばgccだが、C 99が現れ、Cにこの特性を加えた.元はすべてすべて良くなって、しかし杯具のC 99のinlineと多くのコンパイラの以前プラスしたあの用法は完全に同じではありませんて、もしあなたがgccの風格のinlineに慣れたら、きっと注意してください、私はネット上でこれを見つけて、見てみましょう:
http://blog.163.com/zhaojie_ding/blog/static/172972895200811545032240
5.リロード関数
現実の生活の中の1つの言葉には多くの意味があるかもしれません.例えば、洗濯、シャンプー、洗車には、1つの洗字がありますが、彼らの操作方法は違います.関数も同様で、操作が全く同じではない場合がありますが、名前が同じである場合があります.これがリロード関数です.
リロード関数とは、2つ以上の関数は同じ関数名を取りますが、関数パラメータの個数やタイプが異なり、コンパイラは実際に関与するパラメータのタイプと個数に基づいて最適に一致し、どの関数を呼び出すかを自動的に決定します.なぜリロード関数があるのですか?リロード関数がない場合、異なるタイプのデータに対して同様の操作を行い、加算関数などの異なる名前の関数を定義するには、整数加算と浮動小数点数加算に対してそれぞれ異なる関数名を定義する必要があります.
int nadd(int a, int b);
float fadd(float a, float b);
このように呼び出すには覚えなければならない関数名が多すぎて、機能が似ていて不便です.これはC++の構文特性であり,クラスの作成時にコンストラクション関数を記述する際に実用的である.たとえば、三角形というクラスtriangleがあり、1つ以上のパラメータで作成できます.
new triangle(x);//等辺三角型、辺長xを作成
new triangle(x,y);//二等辺三角形、底x、腰yを作成
new triangle(x,y,z);//一般的な三角形を作成
上のようにするには、3つの構造関数を再ロードすればいいです.
6.テンプレート関数
リロード関数を使用すると、絶対値を求める2つの関数など、最適な効果が得られない場合があります.
int abs(int x)
{
return x<0 ? -x:x;
}
double abs(double x)
{
return x<0 ? -x:x;
}
この2つの関数を観察すると、この2つの関数は戻り値のタイプとパラメータのタイプが異なるだけで、機能は完全に同じで、共通のコードを書く方法があれば、多くの異なるデータ型に適用することができます.つまり、上記のように2つの関数を書かずに世代コードだけで2つの関数の機能を実現することができます.コードの多重性はもっと高いのではないでしょうか.開発効率も向上します.これは関数テンプレートで実現されます.関数テンプレートの定義形式は次のとおりです.
template
関数の定義
そう、テンプレート関数はすでにテンプレートに設計されています.そして、最も重要なのは、OOPの思想ではなく、より高いレベルのモデルです.つまり、汎用プログラミングです.明らかにこれはC with Classから遠すぎる.
第二部分:プロセス向けのプログラミングスタイル
何がプロセスに向いているのか分からないなら、あなたは絶対にCプログラマーではないと思います.実は私は个人的にプロセスに向いて、モジュール式のCプログラミングの风格は最もすばらしい范式だと感じて、ふだん私达が出会った大多数の问题のため、すべてこのような范式で解决することができて、その上设计はかなり简洁で明快で、决して泥を引きずって水を持っていないで、逆にひっきりなしに対象の型に向かって本当にあなたを问题の本质からますます远く离れさせます.プロセスのパターンにどんなに慣れていても、C++環境ではいくつかの違いがあります.
1.参照について:
引用は現代のプログラミング言語によくある概念であり、自然にC++が導入した新しい言語特性でもあり、C++でよく使われる重要な内容である.しかし、私はツッコミを入れないわけにはいきません.他のオペレータを使ってはいけませんか.Cを使って開発することに慣れている友人たちは、c++に現れる&記号を見て、ぼんやりするかもしれません.C言語ではこの記号はアドレスを取る記号を表していますが、C++では引用を表すために使われているので、多くの混乱した書き方が発生しています.
#include
{ int a = 0;//&a = 0x0012ff60
int *p = &*(int*)0x0012ff60;
printf("The value is: %d", *p);
return 0;
}
私は本当に貼りたくなくて、見るたびに吐き気がして、、とにかくこれはとても奇抜な現象で、針という究極の武器がある言語の中で引用を導入して、本当に混乱しています.私の提案は次のとおりです.
a)もしあなたがC++プログラマーなら、あなたの引用を使ってください.ポインタをいじってはいけません.
b)逆にあなたはCプログラマーですから、自愛して、引用から離れてください!!少なくともC with Classでは使用禁止です.
2.newとdeleteの使用上の注意
これまでnewとdeleteオペレータは私が受け入れた唯一のC++の中のもので、相手に向かうために受け入れざるを得なかった以上、彼らをよく使わなければなりません.
新用法:
1.単一変数アドレス空間を開く
1)int *a = new int;//格納配列の格納空間を開き、その格納空間を指すアドレスを返す.int*a=new intは、intタイプのアドレスを整数ポインタaに付与ものである.
2)int *a = new int(5);//作用は同じですが、同時に整数を5に割り当てます.
2.アレイスペースを開く
int *a = new int[100];//サイズ100の整数配列空間を開く
deleteの使い方:
1. delete a;//個々のintのスペースを解放する
2. delete [] a;//int配列空間の解放
deleteとdelete[]の違いに注意してください.C++は、newで割り当てられた単一オブジェクトのメモリスペースを回収するときにdelete、new[]で割り当てられたオブジェクトのセットのメモリスペースを回収するときにdelete[]を使用することを教えてくれます.new[]とdelete[]については、(1)基本データ型の割り当てと回収空間;(2)カスタムタイプにスペースを割り当て、回収します.
次の手順を参照してください.
#include <iostream>;
using namespace std;
class T {
public:
T() { cout << "constructor" << endl; }
~T() { cout << "destructor" << endl; }
};
int main()
{
const int NUM = 3;
T* p1 = new T[NUM];
cout << hex << p1 << endl;
// delete[] p1;
delete p1;
T* p2 = new T[NUM];
cout << p2 << endl;
delete[] p2;
}
皆さんは自分でこのプログラムを実行して、delete p 1とdelete[]p 1の異なる結果を見て、私はここで実行結果を貼りません.実行結果からdelete p 1は空間を回収する過程でp 1[0]というオブジェクトだけが構造関数を呼び出し,p 1[1]、p 1[2]などの他のオブジェクトは自身の構造関数を呼び出していないことが問題であることが分かる.delete[]を使用すると、スペースを回収する前にすべてのオブジェクトが最初に独自の構造関数を呼び出します.基本タイプのオブジェクトには構造関数がないので、基本タイプからなる配列空間を回収するにはdeleteとdelete[]を使用することができるはずです.ただし、クラスオブジェクト配列ではdelete[]しか使用できません.newの単一オブジェクトの場合、delete[]でスペースを回収することはできません.
したがって、簡単な使用原則は、newとdelete、new[]とdelete[]が対応して使用されることです.
3.関数パラメータのデフォルト
そう、多くのCプログラマーは、C++が関数パラメータにデフォルト値を割り当てることができることをとっくに知っていて、呼び出し時に指定しない場合はデフォルト値を使用します.私はこの特性が本当にとても悪くないと思って、APIを设计するために极めて便利を提供することができて、しかしCの中ではありませんて、もしあなたの强迫症が特に深刻ではありませんならば、私はこの特性を受け入れることができると思って、もし不幸にも铳に当たっても心配しないで、実はCを使って私达もこの特性をシミュレートすることができて、最も鋭いMacroを使います!!
具体的なやり方は以下の通りです.
1 #include<stdio.h>
2
3
4
5 enum{
6
7 plain=0,italic=1,bold=2
8
9 };
10
11
12
13 void printString(const char* message, int size, int style) {
14
15 printf("%s %d %d
",message,size,style);
16
17 }
18
19
20
21 #define PRINT_STRING_1_ARGS(message) printString(message, 18, italic)
22
23 #define PRINT_STRING_2_ARGS(message, size) printString(message, size, italic)
24
25 #define PRINT_STRING_3_ARGS(message, size, style) printString(message, size, style)
26
27
28
29 #define GET_4TH_ARG(arg1, arg2, arg3, arg4, ...) arg4
30
31 #define PRINT_STRING_MACRO_CHOOSER(...) \
32
33 GET_4TH_ARG(__VA_ARGS__, PRINT_STRING_3_ARGS, \
34
35 PRINT_STRING_2_ARGS, PRINT_STRING_1_ARGS, )
36
37
38
39 #define PRINT_STRING(...) PRINT_STRING_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
40
41
42
43 int main(int argc, char * const argv[]) {
44
45 PRINT_STRING("Hello, World!");
46
47 PRINT_STRING("Hello, World!", 12);
48
49 PRINT_STRING("Hello, World!", 12, bold);
50
51 return 0;
52
53 }
はい、確かに複雑で、実際には適切に簡略化することができますが、もしあなたが本当にライブラリを設計したいなら、上の完全な書き方は本当に素晴らしいですよ.そして移植性が高いですね.もちろん、これは私が考えたものではありません.元のリンクはここにあります.
http://stackoverflow.com/questions/3046889/optional-parameters-with-c-macros
4.inline関数
以前のCはinlineというものはありませんでしたが、頻繁に使う小さな関数については、マクロ関数と書くことが多く、関数展開のオーバーヘッドを低減することができます.しかしC++はあり、多くのコンパイラもCにこの拡張を加えた.例えばgccだが、C 99が現れ、Cにこの特性を加えた.元はすべてすべて良くなって、しかし杯具のC 99のinlineと多くのコンパイラの以前プラスしたあの用法は完全に同じではありませんて、もしあなたがgccの風格のinlineに慣れたら、きっと注意してください、私はネット上でこれを見つけて、見てみましょう:
http://blog.163.com/zhaojie_ding/blog/static/172972895200811545032240
5.リロード関数
現実の生活の中の1つの言葉には多くの意味があるかもしれません.例えば、洗濯、シャンプー、洗車には、1つの洗字がありますが、彼らの操作方法は違います.関数も同様で、操作が全く同じではない場合がありますが、名前が同じである場合があります.これがリロード関数です.
リロード関数とは、2つ以上の関数は同じ関数名を取りますが、関数パラメータの個数やタイプが異なり、コンパイラは実際に関与するパラメータのタイプと個数に基づいて最適に一致し、どの関数を呼び出すかを自動的に決定します.なぜリロード関数があるのですか?リロード関数がない場合、異なるタイプのデータに対して同様の操作を行い、加算関数などの異なる名前の関数を定義するには、整数加算と浮動小数点数加算に対してそれぞれ異なる関数名を定義する必要があります.
int nadd(int a, int b);
float fadd(float a, float b);
このように呼び出すには覚えなければならない関数名が多すぎて、機能が似ていて不便です.これはC++の構文特性であり,クラスの作成時にコンストラクション関数を記述する際に実用的である.たとえば、三角形というクラスtriangleがあり、1つ以上のパラメータで作成できます.
new triangle(x);//等辺三角型、辺長xを作成
new triangle(x,y);//二等辺三角形、底x、腰yを作成
new triangle(x,y,z);//一般的な三角形を作成
上のようにするには、3つの構造関数を再ロードすればいいです.
6.テンプレート関数
リロード関数を使用すると、絶対値を求める2つの関数など、最適な効果が得られない場合があります.
int abs(int x)
{
return x<0 ? -x:x;
}
double abs(double x)
{
return x<0 ? -x:x;
}
この2つの関数を観察すると、この2つの関数は戻り値のタイプとパラメータのタイプが異なるだけで、機能は完全に同じで、共通のコードを書く方法があれば、多くの異なるデータ型に適用することができます.つまり、上記のように2つの関数を書かずに世代コードだけで2つの関数の機能を実現することができます.コードの多重性はもっと高いのではないでしょうか.開発効率も向上します.これは関数テンプレートで実現されます.関数テンプレートの定義形式は次のとおりです.
template
関数の定義
そう、テンプレート関数はすでにテンプレートに設計されています.そして、最も重要なのは、OOPの思想ではなく、より高いレベルのモデルです.つまり、汎用プログラミングです.明らかにこれはC with Classから遠すぎる.