2013年12月28日土曜日

C++ 純粋仮想関数




今回はオーバーライドにまつわるお話
其の参 です。(^-^)


純粋仮想関数とは、基底クラスで内容を
定義せずに派生クラスで関数の内容を
定義する関数です。

ややこしくなってしまった...


使いどころとしては、必ず継承して使うようなクラスの場合です。(^^;)
そのような場合は、基底クラスで仮想関数の内容を決められないからです。

class Food
{
public:
    //最初に virtual と書き、最後に = 0 と書く
    virtual void SetPrice(int price) = 0;
    int GetPrice(void);
protected:
    int m_price;
};

基底クラスでは、このように呼び出し方だけを記載しておきます。
注意する点は、純粋仮想関数を含むオブジェクトは生成できないということです。

間違ってオブジェクトを作ろうとすると、当然コンパイルエラーです(*´Д`)
そう、こんな風に...

test.cpp: In function ‘int main()’:
test.cpp:59:10: error: cannot declare variable ‘myFood’ to be of abstract type ‘Food’
test.cpp:6:7: note:   because the following virtual functions are pure within ‘Food’:
test.cpp:10:18: note:        virtual void Food::SetPrice(int)

それと、ひっそりとメンバ変数が protected に変わっています...
もし、private のままだと、勿論コンパイルエラーです(*´Д`)
派生クラスからアクセスできませんので当然です。
まぁ、こんな風に...

test.cpp: In member function ‘virtual void Vegetable::SetPrice(int)’:
test.cpp:14:9: error: ‘int Food::m_price’ is private
test.cpp:31:5: error: within this context
test.cpp: In member function ‘virtual void Meet::SetPrice(int)’:
test.cpp:14:9: error: ‘int Food::m_price’ is private
test.cpp:43:5: error: within this context

派生クラスでは、継承した純粋仮想関数をオーバーライドして
何をするかを定義します。

それでは、サンプルプログラムです。
#include <iostream>
#include <string.h>

using namespace std;

class Food
{
public:
    //純粋仮想関数
    virtual void SetPrice(int price) = 0;
    int GetPrice(void);
protected:  //protectedにしておかないと、継承先で参照できない
    int m_price;
};

int Food::GetPrice(void)
{
    return m_price;
}

//派生クラスVegetable
class Vegetable : public Food
{
public:
    void SetPrice(int price);
};

void Vegetable::SetPrice(int price)
{
    m_price = price * 2;
}

//派生クラスMeet
class Meet : public Food
{
public:
    void SetPrice(int price);
};

void Meet::SetPrice(int price)
{
    m_price = price / 2;
}

int main(void)
{
    Food *pFood;
    Vegetable myVegetable;
    Meet myMeet;

    pFood = &myVegetable;
    pFood->SetPrice(500);    //VegetableクラスのSetPrice()を呼び出す
    cout << "Vegetable Price = " << pFood->GetPrice() << endl;
    pFood = &myMeet;
    pFood->SetPrice(1500);    //MeetクラスのSetPrice()を呼び出す
    cout << "Meet Price = " << pFood->GetPrice() << endl;

    return 0;
}

実行結果
# ./test
Vegetable Price = 1000
Meet Price = 750

ハマる楽しさオーバーライド これもC++のいいところです(^^)

今日の名言
不眠症で眠れないのは、不眠症を気にするからだ。
なぜ気になるかといえば、眠らないからだ。
                     フランクリン・ピアース・アダムス

忍耐はどんな悩みにも効く名薬である。
                     プラウトゥス

私は貧乏と病気のどん底を生き抜いてきました。「あらゆる人に振りかかる
悩みをあなたはどうやって切り抜けてきたのですか」と尋ねる人があれば、
私はいつもこう答えます。「私は昨日耐えました。今日も耐えることができます。
そして明日のことは決して考えないようにしています」
                     ドロシー・ディックス

2013年12月25日水曜日

C++ 仮想関数とオーバーライド


今回はオーバーライドにまつわるお話 其の弐 です。(^-^)

仮想関数とオーバーライドとは
派生クラスで再定義したメンバ関数を

基底クラスのポインタから呼び出すと

通常は再定義前のメンバ関数
(基底クラスのメンバ関数のこと)
が呼ばれます。



ここで再定義後のメンバ関数が呼ばれるようにするには、基底クラスで
その関数を仮想関数にしておく必要があります(^^;)

仮想関数にするには、予約語 virtual を指定します。
そして、仮想関数を派生クラスで定義し直すことをオーバーライドといいます。

では、仮想関数の使用例です。
class Food
{
public:
    virtual void SetPrice(int price);  //仮想関数を定義
    int GetPrice(void);
private:
    int m_price;
};
   :
void Vegetable::SetPrice(int price)  //派生クラスで
{                                                 //SetPrice()をオーバーライド
    Food::SetPrice(price * 2);           //倍返し価格設定
}
   :
int main(void)
{

    Food *pFood;
    Vegetable myVegetable;

    pFood = &myVegetable;
    pFood->SetPrice(500);    //VegetableクラスのSetPrice()を呼び出す
   :

実行結果
# ./test
Vegetable Price = 1000

「オーバーライド」と「オーバーロード」は言葉が似ています...
いつもごっちゃになるので注意したいところです(^^;)

今回のソース
#include <iostream>
#include <string.h>

using namespace std;

class Food
{
public:
    virtual void SetPrice(int price);
    int GetPrice(void);
private:
    int m_price;
};

class Vegetable : public Food
{
public:
    void SetPrice(int price);
    void SetFarmName(const char *farm);
    char *GetFarmName(void);
private:
    char m_strFarmName[32];
};

void Food::SetPrice(int price)
{
    m_price = price;
}

int Food::GetPrice(void)
{
    return m_price;
}

void Vegetable::SetPrice(int price)
{
    Food::SetPrice(price * 2);
}

void Vegetable::SetFarmName(const char *farm)
{
    strncpy(m_strFarmName, farm, 32);
}

char *Vegetable::GetFarmName(void)
{
    return m_strFarmName;
}

int main(void)
{

    Food *pFood;
    Vegetable myVegetable;

    pFood = &myVegetable;
    pFood->SetPrice(500);    //VegetableクラスのSetPrice()を呼び出す

    cout << "Vegetable Price = " << pFood->GetPrice() << endl;

    return 0;
}

今日の名言
満面にこぼれるような笑みをたたえ、肩をそびやかし、大きく深呼吸しながら歌の
一節でも口ずさむことだ。歌でなくて口笛でも良い。口笛が駄目なら鼻歌でも良い。
早い話が、幸福に酔いしれているようにふるまいながら、同時に浮かぬ顔で沈み込んで
いることは肉体的に不可能だということだ!
                                   デール・カーネギー

頭を悩ませる問題にぶつかった時でも、私は一時間以内にそうした悩みを追放して、
「素晴らしきかな人生」と歌声を上げることができる。私のやり方はこうだ。自分の
書斎へ入り、目を閉じたままで私は本を一冊抜き出す。それがこのプレスコットの
「メキシコ征服記」であろうとスエトニウスの「ローマ帝王記」であろうと、いっこうに
構わない。なおも目を閉じたままで、行き当たりばったりにページを開く。それから
目を開けて一時間読みふける。読めば読むほど、私は、世界が常に苦悶にあえいで
きたこと、文化が常に破滅の一歩手前にあったことを、痛感するのである。歴史書の
各ページは、戦争、飢餓、貧窮、疫病、人間同士の非人道的行為について、あますところ
なく述べている。一時間歴史をひもといてのち私は、なるほど現状はひどいには
違いないが、過去に比べるならはるかに良くなっていることをしみじみと悟る。
これにより、大局的には世界はだんだん良い方向に向かっていることが把握でき、
また私の悩みも、そのありのままの姿から検討できる。
                                   ロジャー・W・バブソン

2013年12月23日月曜日

C++ メンバ関数の再定義


今回はオーバーライドにまつわるお話
其の壱 です。(^-^)

基底クラスのメンバ関数の再定義
基底クラスのメンバ関数は、派生クラスで
定義しなおすことができます。

この場合は、関数名、引数、戻り値が
同じでなければなりません。
定義しなおすと、そちらの関数が
呼ばれるようになります(^^)


ここでは、基底クラスFoodに対し、派生クラスVegetableで
SetPrice()関数を再定義してみます。

class Food
{
public:
    void SetPrice(int price);
    int GetPrice(void);
private:
    int m_price;
};

class Vegetable : public Food
{
public:
    void SetPrice(int price);
    void SetFarmName(const char *farm);
    char *GetFarmName(void);
private:
    char m_strFarmName[32];
};
   :
void Vegetable::SetPrice(int price)    //SetPrice()の再定義
{
    Food::SetPrice(price / 2); //半額にする
}

派生クラスから、基底クラスの関数を呼ぶときは
スコープ解決演算子を使います(^^)

実行結果
# ./test
Food Price = 500
Vegetable Price = 250

どうでしょうか、関数名が被ってもいいってのは、名前に悩まされる問題が
軽減される気がします。
なぜなら、機能が同じなのでそういった名前が付けたいに違いない!
と思うわけでして...(^^;)

せっかくなので、一応全部載せときます...
#include <iostream>
#include <string.h>

using namespace std;

class Food
{
public:
    void SetPrice(int price);
    int GetPrice(void);
private:
    int m_price;
};

class Vegetable : public Food
{
public:
    void SetPrice(int price);
    void SetFarmName(const char *farm);
    char *GetFarmName(void);
private:
    char m_strFarmName[32];
};

void Food::SetPrice(int price)
{
    m_price = price;
}

int Food::GetPrice(void)
{
    return m_price;
}

void Vegetable::SetPrice(int price)
{
    Food::SetPrice(price / 2);
}

void Vegetable::SetFarmName(const char *farm)
{
    strncpy(m_strFarmName, farm, 32);
}

char *Vegetable::GetFarmName(void)
{
    return m_strFarmName;
}

int main(void)
{

    Food myFood;
    Vegetable myVegetable;

    myFood.SetPrice(500);         //FoodクラスのSetPrice()
    myVegetable.SetPrice(500);    //VegetableクラスのSetPrice()

    cout << "Food Price = " << myFood.GetPrice() << endl;
    cout << "Vegetable Price = " << myVegetable.GetPrice() << endl;

    return 0;
}


今日の名言
問題を手際よく表現することによって、問題は半ば解決されている。
                                チャールズ・F.・ケタリング

一種類以上の問題を無理に抱えようとするな。世の中には三種類も問題を抱えている
人がある-過去の問題のすべて、現在の問題のすべて、未来の問題のすべてを。
                                エドワード・エヴァレット・ヘール

私たちが敵に憎しみを感じると、むしろ自分自身が敵に支配されることになる。そして
その支配力は私たちの睡眠・食欲・血圧・健康・幸福にまで及んでくる。敵について
思い悩み、苦悶し、何とか仕返しの機会を狙っていると知ったら、敵は小躍りして
喜ぶであろう!私たちの憎悪は少しも敵を傷つけないばかりか、かえって私たち自身が
日夜、地獄の苦しみを味わうことになる。
                                デール・カーネギー

2013年12月18日水曜日

C++ 派生クラスと基底クラス 其の弐


今回は、派生クラスのオブジェクトのアドレスを
基底クラスのポインタに代入するとどうなるのか、
について見ていきます(^^)

子オブジェクトのアドレスを親クラスのポンタに代入してみると
何と派生クラスのオブジェクトのアドレスを、
基底クラスのポインタに代入するといった
使い方もできます。





class Food  //基底クラス
{
public:
    void SetPrice(int price);
    int GetPrice(void);
private:
    int m_price;
};

class Vegetable : public Food //派生クラス
{
public:
    void SetFarmName(const char *farm);
    char *GetFarmName(void);
private:
    char m_strFarmName[32];
};
   :
   :
int main(void)
{
    Food *pFood;         //Foodクラスのポインタ
    Vegetable myVegetable;  //Vegetableクラスのオブジェクト

    pFood = &myVegetable;  //Vegetableクラスのオブジェクトのアドレスを
                                        //Foodクラスのポインタに代入
    return 0;
}


使い方をもっと具体的に
基底クラスのポンタ配列に派生クラスからのオブジェクトのアドレスを代入しておくと、
派生クラスのメンバ関数を基底クラスのポインタから呼び出すことができます(^^)
以前のサンプルプログラムを以下のように変更します。

    :
class Meet : public Food    //新しい派生クラスMeetを追加
{
public:
    void SetFarmName(const char *farm);
    char *GetFarmName(void);
private:
    char m_strFarmName[32];
};
    :
int main(void)
{
    Food *pFood[2];
    Vegetable myVegetable;
    Meet myMeet;

    pFood[0] = &myVegetable;
    pFood[1] = &myMeet;

    for (int i = 0; i < 2; i++) {
        pFood[i]->SetPrice((i+1) * 100);
        cout << "Price[" << i << "]="<<  pFood[i]->GetPrice() << endl;
    }

    return 0;
}

実行結果
# ./test
Price[0]=100
Price[1]=200

継承に限らず、ポインタを駆使した処理というのは沢山でてきますので
ぜひとも身につけておきたいところです(^^;)


今日の名言
いらぬ取り越し苦労をするよりも、前もって考えたり計画する方が大事だ。
                                ウィンストン・チーチャル

大きな悲しみには勇気をもって立ち向かい、小さな悲しみには忍耐をもって立ち向かえ。
一日の仕事を終えたら安らかに眠れ。あとは神が守ってくださる。
                                ヴィクトル・ユーゴー

小さな事柄が人を悩ませるのだ。象が向って来れば身をかわして逃げられもするが、
ハエからは身をかわすことはできない。
                                ジョシュ・ビリングス

人間を殺すのは仕事ではない。悩みである。仕事は健康に良い。けれど自分の力の
限界以上に働くことはできない。悩みは歯車の錆である。機械が駄目になるのは、
絶えず回転するからではなく、絶えず摩擦するからである。
                                ヘンリー・ウォード・ビーチャー

2013年12月16日月曜日

C++ 派生クラスと基底クラス 其の一

今回は、派生クラスのオブジェクトを基底クラスへ代入するという
ことについて見ていきます(^^)

子オブジェクトを親オブジェクトに代入してみる
派生クラスのオブジェクトは、基底クラスのオブジェクトへ
代入することができます。
代入すると、派生クラスのメンバ変数の値が、
そのまま対応する基底クラスのメンバ変数にコピーされるのです(^^)/ さすがC++ 賢い!

かなり省略してますが、以前のプログラムを利用した例です。

class Food
{
    :               //基底クラスFoodの定義
};

class Vegetable : public Food
{
    :              //派生クラスVegetableの定義
};

    :

int main(void)
{
    Vegetable Pumpkin;  //Pumpkinオブジェクト生成
    Food myFood;         //myFoodオブジェクト生成

    Pumpkin.SetPrice(398);
    cout << "Price = " << Pumpkin.GetPrice() << endl;

    Pumpkin.SetFarmName("Pascal's Farm");
    cout << "Farm Name = " << Pumpkin.GetFarmName() << endl;

    myFood = Pumpkin;  //Pumpkinオブジェクトを代入
    cout << "myFood's price " << myFood.GetPrice() << endl;
  
    return 0;
}

実行結果はこうなります。(^^)
# ./test
Price = 398
Farm Name = Pascal's Farm
myFood's price 398

おぉ、Foodクラスの方では、SetPrice() を呼び出していないのに
価格が設定されているではありませんか!

親オブジェクトを子オブジェクトへ代入してみると?
一方で、基底クラスのオブジェクトを派生クラスのオブジェクトに
代入するとどうなるのでしょう。試してみます。(^^;)

int main(void)
{
    Vegetable Pumpkin;
    Food myFood;

    Pumpkin.SetPrice(398);
    cout << "Price = " << Pumpkin.GetPrice() << endl;

    Pumpkin.SetFarmName("Pascal's Farm");
    cout << "Farm Name = " << Pumpkin.GetFarmName() << endl;

    myFood.SetPrice(200);  //基底クラスに設定した値が   
    Pumpkin = myFood;      //派生クラスに反映されるのでしょうか?

結果は、コンパイルエラーです...(*´Д`)
派生クラスにしかないメンバ変数に値が設定できないのです。
これでは困るので、親から子へ代入ができないのです。

ちなみに、こんなメッセージが出ます。
test.cpp: In function ‘int main()’:
test.cpp:57:15: error: no match for ‘operator=’ in ‘Pumpkin = myFood’
test.cpp:57:15: note: candidate is:
test.cpp:15:7: note: Vegetable& Vegetable::operator=(const Vegetable&)
test.cpp:15:7: note:   no known conversion for argument 1 from ‘Food’ to ‘const Vegetable&’

実は、もっと後に出すつもりの演算子のオーバーロードという機能を使えば
このエラーそのものは、無くすことができます。
ただし、それはまた後ほど...(^^;)

今日の名言
ふとっちょ卵が塀の上、ふとっちょ卵が落ちちゃった。
王様の馬と王様の家来が皆出て来てくっつけたけど、元通りにはならないよ。
この古い童話にある通り、王様の馬と家来が全部束になってかかっても、過去は
元通りにはならない。一旦おがくずになったものをのこぎりで挽いても始まらない。
                                デール・カーネギー

私は実業界に入って間もなく、心配することのばからしさを思い知らされた。だから
私は、難問にはできる限り手を尽くすように心がけているが、もし目算が外れて、
収拾がつかなくなったとしても、あっさり忘れることにしている。
                                ジュリアス・ローゼンウォルト

私は他に気がかりなことがあるとしても、それに関連する事柄全てを忘れ去り、
当面の仕事に没頭することにしている。その効果は実に素晴らしい。
                                ヘンリー・ウォード・ビーチャー

2013年12月11日水曜日

C++ 多重継承

複数の基底クラスから一つの派生クラスを作ることができます。
これを多重継承といいます。(^^)
一方、一つの基底クラスから派生クラスを作ることを単一継承といいます。

多重継承の一例です。

Copyクラス Scannerクラス  Printerクラス Faxクラス
 Copy()         Scan()            Print()          Fax()
  Switch()       Switch()          Switch()        Switch()
 |_____|______|____|
               |
              MFPクラス

MFPとは、MultiFunctionPrinter Pは Procduct ということも...
要は複合機です。

MFPクラスは、他のクラスのメンバをすべて含んでいます。
すなわち、MFPクラスからCopyクラスに定義してある関数が
使用できるということになります。(^^)

多重継承の定義の仕方
多重継承の定義は、基底クラスを「, (カンマ)」で区切って記述します。

class MFP : public Copy, public Scanner, public Printer, public Fax
{
    :
    :
};

多重継承はメンバが曖昧になる
多重継承で、もし複数の基底クラスに同じ名前のメンバがあった場合、
派生クラスには同じ名前のメンバが複数出来てしまうことになります。

先の例では、すべてのクラスに 関数 Switch() があるため、
MFPクラスでは、4つの Switch()が出来るのです(^^;)

派生クラスからこれらの重複したメンバにアクセスするには、
スコープ解決演算子を使います。

class Copy
{
public:
    int GetSwitchStat(void) { return m_on; }
    void SetSwitch(int n) { m_on = n; };  //Copyクラスのメンバ関数SetSwitch()
private:
    int m_on;
};

class Scanner
{
public:
    int GetSwitchStat(void) { return m_on; }
    void SetSwitch(int n) { m_on = n; };  //Scannerクラスのメンバ関数SetSwitch()
private:
    int m_on;
};

class Printer
{
public:
    int GetSwitchStat(void) { return m_on; }
    void SetSwitch(int n) { m_on = n; };  //Printerクラスのメンバ関数SetSwitch()
private:
    int m_on;
};

class Fax
{
public:
    int GetSwitchStat(void) { return m_on; }
    void SetSwitch(int n) { m_on = n; };  //Faxクラスのメンバ関数SetSwitch()
private:
    int m_on;
};

class MFP : public Copy, public Scanner, public Printer, public Fax
{
public:
    int GetSwitchStat(void) { return m_on; }
private:
    int m_on;
};

int main(void)
{
    MFP mfp;
    mfp.SetSwitch(0);  //MFPクラスのオブジェクトからメンバ関数を呼び出す?
        :

これではコンパイラはどのSetSwitch()を使うか判断できません。
そのため、コンパイルエラーになります。(*´Д`)

# g++ -g -Wall -o test test.cpp
test.cpp: In function ‘int main()’:
test.cpp:52:9: error: request for member ‘SetSwitch’ is ambiguous
test.cpp:36:10: error: candidates are: void Fax::SetSwitch(int)
test.cpp:27:10: error:                 void Printer::SetSwitch(int)
test.cpp:18:10: error:                 void Scanner::SetSwitch(int)
test.cpp:9:10: error:                 void Copy::SetSwitch(int)
r
同名のメンバがあるときは、スコープ解決演算子を使って、
どのクラスのメンバを呼び出すのかを指定してください。

int main(void)
{
    MFP mfp;
    mfp.Fax::SetSwitch(0);  //Faxクラスの

    cout << "MFP switch1 " << mfp.Fax::GetSwitchStat() << endl;
    cout << "MFP switch2 " << mfp.GetSwitchStat() << endl;
        :

# ./test
MFP switch1 0
MFP switch2 34332

この例では、MFPクラスの m_on には値を設定していないので
不定値が出力されています。
このことからも、多重継承によって、メンバ変数 m_on が
5つあるということがわかります。(^^;)
 
今日の名言
明朗になろう。耐え切れぬほどひどい不幸など、ありえないのだから。
                             ジェイムズ・ラッセル・ローウェル

私はあきれ返った楽天家として通っているが、まさにそのとおりである。私は成功のこと
ばかり考え、決して失敗のことを考えないからだ。こうして、知らず知らずのうちに不幸に
背を向け、失敗を恐れる気持ちを消し去る。私はこうして自分の人生哲学を実行している。
どんな仕事も必ず十分に検討して、自分の力でやれるのはどの程度か、はっきり見極める
ことだ。それからこの目標をどうやって遂行するか計画を立てる。その際、他人の方法を
真似てはいけない、自分独自の方法を考え出して計画することだ。
                             フェルディナンド・フォシュ将軍

私たちの疲労は仕事によって生じたのではなく、悩み、挫折、後悔が
原因となっていることが多い。
                             デール・カーネギー

2013年12月9日月曜日

C++ 継承したメンバへのアクセス

今回は、継承したメンバのアクセス制限についての話です。

基底クラスでのpublicメンバの場合
基底クラスでpublicだったメンバは、派生クラスからは自分のクラスのメンバと
同じようにアクセスすることができます(^^)

class Food {
public:
    int GetPrice() { return price; }
};

class Vegetable : public Food {
public:
    void Vegetable::PricePrice() {
        cout << "Price = " << GetPrice() << endl;
    }
};

Vegetableクラスでは、基底クラスでpublicだったメンバ関数のGetPrice()に
アクセスしています。
基底クラスでpublicだったメンバは呼び出せるのです(^^)/


基底クラスでのprivateメンバの場合
基底クラスでprivateだったメンバは、派生クラスからはアクセスすることはできません。

class Food {
private:
    int m_price;
};

class Vegetable : public Food {
public:
    void Vegetalbe::PrintPrice() {
        cout << "Price = " << m_price << endl;
    }
};

基底クラスでprivateメンバにアクセスしようとすると、コンパイルエラーです。

そう、こんな風に(*´Д`)
test.cpp:12:10: error: extra qualification ‘Vegetable::’ on member ‘PrintPrice’ [-fpermissive]
test.cpp: In member function ‘void Vegetable::PrintPrice()’:
test.cpp:7:9: error: ‘int Food::m_price’ is private
test.cpp:13:31: error: within this context

基底クラスでprivateだったものは使えないのです(-_-;)


アクセス指定子のprotected
protectedを使用した場合は、派生クラスからアクセスできても
他のクラスやグローバルな関数からアクセスできなくなります。(^^;)

class Food {
protected:
    int m_price;
};

class Vegetable : public Food {
public:
    void Vegetable::PrintPrice() {
        cout << "Price = " << m_price << endl;  //これはOK
    }
};

int main(void)
{
    Vegetable vgt;
    vgt.PrintPrice();

    vgt.m_price = 200;
        :

例えば、こんな風に使おうとすると、コンパイルエラーになってしまいます...

そう、こんな感じで(*´Д`)
test.cpp:12:10: error: extra qualification ‘Vegetable::’ on member ‘PrintPrice’ [-fpermissive]
test.cpp: In function ‘int main()’:
test.cpp:7:9: error: ‘int Food::m_price’ is protected
test.cpp:22:9: error: within this context

アクセス指定子は、要注意ですね(^^;)
たまに、設計の意図を汲み取らず、これ public にしたいなぁという事はあるのですが...

今日の名言
心を傷つける鎖を断ち切り、悩みをきっぱりと捨て去った者は、幸福なるかな。
                           オウィディウス

明日を耐え抜くために必要なものだけ残して、あらゆる過去を閉め出せ。
                     サー・ウィリアム・オスラー

過ぎ去ったものは、もはや再び帰らない。賢者は現在と未来について考えるだけで
手一杯であるから、過ぎ去った事柄をくよくよ考えている暇がない。
                           フランシス・ベーコン

ジョージ・ハーバードは「夜は魂を脱ぎ捨てよ」と言っている。これは内省を
しろというのではなく、服を脱ぐようにすっぽりと魂を脱ぎ捨てるのだ。その
一日をなすこともなく過ごした罪も、誤りを犯した罪も、ともに脱ぎ捨てれば、
翌朝新しい命を持った新しい人間として、目覚めるだろう。
                     サー・ウィリアム・オスラー

恐ろしい悪夢に比べれば、現在の恐怖のほうがまだましだ。
                     ウィリアム・シェイクスピア

2013年12月3日火曜日

C++ 継承の利用

今回は継承したクラスのオブジェクトの使用例として、サンプルコードを掲載します(^^)
Foodクラスを継承したVegetableクラスの利用です。

#include <iostream>
#include <string.h>

using namespace std;

class Food
{
public:
    void SetPrice(int price);
    int GetPrice(void);
private:
    int m_price;
};

class Vegetable : public Food
{
public:
    void SetFarmName(const char *farm);
    char *GetFarmName(void);
private:
    char m_strFarmName[32];  //勝手に32文字制限
};

void Food::SetPrice(int price)
{
    m_price = price;
}

int Food::GetPrice(void)
{
    return m_price;
}

void Vegetable::SetFarmName(const char *farm)
{
    strncpy(m_strFarmName, farm, 32);
}

char *Vegetable::GetFarmName(void)
{
    return m_strFarmName;
}

int main(void)
{
    Vegetable Pumpkin;  //カボチャ

    Pumpkin.SetPrice(398);  //398円
    cout << "Price = " << Pumpkin.GetPrice() << endl;

    Pumpkin.SetFarmName("Pascal's Farm"); //生産者 ブレーズ・パスカル
    cout << "Farm Name = " << Pumpkin.GetFarmName() << endl;

    return 0;
}

実行例
# ./test
Price = 398
Farm Name = Pascal's Farm

どうでしょうか、継承に魅力に憑りつかれ、C++にハマってくる気がしませんか?(^^;)

今日の名言
時は悲しみと口論の傷を癒やす。人は皆変わる。
過去の自分はもはや現在の自分ではない。悩む者も悩ます者も、時が経てば別人になる。
                                 ブレーズ・パスカル

私は何か問題を考えたい時、心の引き出しを一つ開ける。問題が解決するとその引き出しを
閉め、また次には別のを開ける。眠りたい時には全部の引き出しを閉める。
                                 ナポレオン

今から一年も経てば、私の現在の悩みなど、およそくだらないものに見えることだろう。
                                 サミュエル・ジョンソン

私達の人生を彩る様々な事象のうち、およそ90パーセントは正しく、10パーセントは誤りで
ある。幸福を願うのなら、やり方としては、正しい90パーセントに力を集中し、誤った
10パーセントは無視すればよい。もし苦悩と悲惨を願い、胃潰瘍になりたいのなら、誤った
10パーセントに力を集中し、栄光に満ちた90パーセントを無視すればよい。
                                 デール・カーネギー