この話ならVC++である必要は無いと思いますよ。
むしろ、C++言語自体の話です。
VC++ではなくてC++言語の勉強をすべきだと思います。
VC++とか言っているのは言語ではなくて開発環境に過ぎません。
開発環境と言語は分けて考えないと後々混乱します。
順番としてはC++言語の勉強をして、VC++などの開発環境で使うと
どうなるのかを学んだ方がより無駄が無くて言いと思います。
私がC++の勉強に使ったのは、
プログラミング講義C++ 柴田望洋プログラミングシリーズ
http://www.amazon.co.jp/exec/obidos/ASIN/4797313366/qid=1092273290/
ref=sr_8_xs_ap_i1_xgl/250-9572726-5432228
です。
そうそう、仮想関数と言うのはクラス派生とかそっちの話まで絡めないと
単体では言われているようにvirtualを付ければ仮想関数ですと言うような
話になってしまいます。
仮想関数がどう使われるのかは、多分その部分だけ読んだのではわかりません。
結論を急ぐのではなく、一度通読することをお勧めします。
一通りの内容を把握しないとそれぞれのパーツの意味がわからないというような
事はあると思いますよ。
その本の書き方にもよりますけれどね。
>柴田望洋
彼の本は、とても正確という印象があります。
学生時代のゼミで強制的に買わされたのが「CプログラマのためのC++入門」\2900也。
各トピック毎に問題があるのですが、のっけから問題が解けなくて解答を参照しました。
そうしたら、
「この程度の問題が解けないようでは、本書を読む資格はありません。ましてや、このプ
ログラムが理解できない人は論外です。基本のC言語に戻って勉強しなおして下さい。」
とありました。311ページです(^^;
しかし、そのプログラムというのが「非実用的で、殆どのソフト屋が否定するであろうコ
ード」だったんです。
その時、「もうコイツの本は絶対買わねぇ、読まねぇ」とゼミ仲間で文句を垂れてまし
た。若かりし日の思い出です(^^;
どうも、仮想関数の動きは理解しているけれども、それを使う場面が想像できない。
ってニアンスを受けるのですが。あってます?
この手の話はケースバイケースなのですが
「オブジェクト指向」及び「デザインパターン」の考え方が必須になります。
(仮想関数など使わなくても仕様を実現する実装は可能だからです。)
私は「GOFデザインパターン」関係の本を読むことをお勧めします。
コレだけでは、不親切かと思うので、簡単に説明してみます。
仮想関数及び純粋仮想関数の主な目的は「インターフェース定義」にあります。
つまり、
「このクラスを継承したクラスは全て、この関数を持ちます!」
という宣言だと思ってください。
簡単な例を・・・ニアンスが伝わればよいので、コンパイル等はしていません。
(ちょっと凝りすぎた!!)
mainが「依頼人」です。
見ての通り「依頼人」は「ブラッド君」の顔も名前も知る事無くターゲットを殺せますよね?
「ブラッド君」もお金は支払われるので満足です。
これならば「ブラッド君」以外の殺し屋を増やすのも誰を派遣するのかも「殺組織」の勝手で
す。
#include <iostream>
// 殺し屋はこんなことが出来なければなりません!という宣言
class IAssasin{
protected:
IAssasin(long reward){ Reward = reward };
public:
long Reward; // 依頼料
virtual int pay(long value) = 0; // 支払い窓口
virtual int kill_order(const char *target) = 0; // 依頼内容
};
// 殺し屋:ブラッド君
class Blood:public IAssasin{ // ブラッド君
public:
Blood():IAssasin(1000000){}; // 100万円
int pay(long value){ // 実際はココに支払われます。
cout << Bloodは << value << 円を受け取った << endl;
}
int kill_order(const char *target){ // 依頼内容はココに届きます。
cout << Bloodは << target << を殺しました << endl;
}
};
// 暗殺組織
class assassin_guild{
private:
IAssasin *assasin_list[10];
long num;
public:
assassin_guild(){ //
num = 0;
assasin_list[num++] = new Blood();
}
static IAssasin* introduction(){ // 暇な人を紹介します。(検索は手抜きw)
return assasin_list[0];
}
};
// 実際の使い方
int main(int argc,char *argv[]){
IAssasin *unknown = assassin_guild();
unknown->pay(unknown.Reward);
unknown->kill_order(argv[1]);
}
------------------------------------
この様なモジュール間の依存性を低くする努力は現実の仕事では非常に有効です。
main()の部分はexeとして配布し、他の部分をDLLで配布すれば、
なにか「ブラッド君」に問題が判明した場合には、代役を作ってDLLで配布することが出来るの
です。
以上、長くなりましたが、参考になりましたでしょうか・・・
たとえがすごいw
Reward が int じゃないあたりにこだわりが感じられますな。
派生して振込先をスイス銀行にすればゴルゴさんになりますな。
ただし暗殺組織を仲介しませんけど ^^;
間違いをさっそく発見したので訂正・・・
// 実際の使い方
int main(int argc,char *argv[]){
assassin_guild a_guild; <-ココ
IAssasin *unknown = a_guild.introduction(); <-ココ
unknown->pay(unknown.Reward);
unknown->kill_order(argv[1]);
}
いや、、やっぱり、変な例えですねぇ~
「実体を知らずに使える」って説明する良い例えが浮かばなかったもので、、、
ブラッド君の他に最低もう1人殺し屋を用意して、assassin_guild::introduction()が常
に同じ値を返すのでなく、kill_order()の中身が人によって違えば、とてもいい例だと思
います。
ちょっと、都合上見れなくなっていた間にこんなにもスレがあるとは・・・
正直びっくりです。
おかげさまで、仮想関数の必要性をつかんできました。
あとは、いろいろロジックを作ったりして完成させていきたいと思います。
みなさん、どうもありがとうございました。