#pragma twice

KAB-studio > プログラミング > #pragma twice > 127 Version 7.07 構造体とクラス

#pragma twice 127 Version 7.07 構造体とクラス

前のページへ 表紙・目次へ 次のページへ

 Version 7.07
構造体とクラス

今回は、前回ごまかしちゃった構造体とクラスの関係について
難しいとか面倒とか言ってたよね
うん、なんて言うか、ややこしい話になるんだよね。まずずばり言うと、
クラスと構造体はほとんど違いはありません
ってことは、構造体をクラスと同じように使えるって事?
そゆこと。たとえば AnimeDlg.h の

class CAnimeDlg : public CDialog
{
// 以下略。

これを

struct CAnimeDlg : public CDialog
{

って変えてビルドしてみて
ほいビルド。あ、通った
というわけで、構造体はクラスと同じ。違いはたった一点、些細なことだ
からこれはあとでね
うんあとで。それより、ならなんで構造体なんてあるの? それに、この
前構造体は〈メンバ関数のないクラス〉だって言ってたし
そう、その辺からが複雑な話になるんだよね。ここで重要なポイントにな
るのは〈歴史〉
れきしぃ?
そう、歴史。今 VC で使ってる C++ 言語っていうのは、 C 言語っていう
プログラミング言語を拡張したものだって前に言ったっけ
ぽろぽろっと
で、構造体は C 言語時代からあったもの、クラスは C++ 言語で加わった
もの
クラスは新しいものなのね。あれ? でも構造体とクラスって同じ物なん
でしょ?
そこがポイント。 C 言語時代の構造体と、 C++ の構造体は、実は機能が
だいぶ違うんです
同じ〈構造体〉なのに?
そう。 C++ 言語になったときに、構造体の機能が〈クラスとほとんど同
じ〉になったんです
ってことは、 C 言語の構造体は、クラスみたいな機能はない?
そゆこと。それが、前に言った〈メンバ関数のないクラス〉なわけ
なるほど。構造体は、 C++ になってメンバ関数って機能が加わったわけ

実際にはもっともっと多くの機能が加わったんだけど、それはクラスの機
能をまず知らないといけないから
また今度?
そういうこと。で、もう少し歴史のお勉強
続きがある?
うん。まず、 API 。ウィンドウズももちろん歴史があって、多くの API 
も同じく昔からあります
そりゃ、 API がなけりゃウィンドウズ操作できないんだもんね
で、そういう昔には C++ がなかったから
 C 言語で作ってた?
だから API にはクラスがないでしょ
そういえばそうだね、クラスがあるのって MFC の方だもんね
そう、 API の不便な部分をクラスの機能で補おうっていうのが MFC の基
本的な趣旨。ちなみに MFC は Microsoft Fundation Class library の略
クラスって入ってるね
それが売りだったからね。 API はすべて C 言語向けに作られてるから、
構造体も
メンバ関数とかないわけだ
前回 RECT を見てもらったけど、 typedef とか使ってたでしょ。あれも
古い C 言語形式の書き方
不便ねー
ちょっと前までは C++ 言語ってそれほどメジャーじゃなかったから
ね。だけど、クラスじゃないと不便なのは違いないわけで、実は MFC に
CRect っていうクラスが用意されてます
便利なためにってわけね

void CAnimeDlg::OnBDraw() 
{
    CRect cRect;
    ::GetWindowRect( GetSafeHwnd(), &cRect );
    TRACE
        ( "%d, %d, %d, %d\n"
        , cRect.left, cRect.top
        , cRect.right, cRect.bottom );
}

……別に全然便利になってないじゃん
これはね。これは前回の RECT 使った時の例と同じ事が CRect でもでき
るってことの確認のために
そういえば、まったく同じに使えるんだね
そう、それもそのはず、 CRect は RECT から継承してるんです。 
AFXWIN.H の中を見てみると

( AFXWIN.H より抜粋)
class CRect : public tagRECT
(抜粋ここまで)

継承って憶えてる?
あるクラスの機能をまるまる使えるクラスを新しく作るんだよね
 Ver 3.1 ( No.026 ) でやったね
この CRect も tagRECT から継承してるから、 RECT と同じに使えるわけ
ね。おおっと言わなくていいよ、 tagRECT と RECT が同じってことは前回
やったのだよね
そうそう、 RECT は tagRECT から typedef されてるからね
……だからー、 CRect が RECT と同じに使えることは分かったけど、便
利って部分は?
そうだねー、たとえば

void CAnimeDlg::OnBDraw() 
{
    CRect cRect;
    ::GetWindowRect( GetSafeHwnd(), &cRect );
    TRACE
        ( "%d, %d\n"
        , cRect.Width(), cRect.Height() );
}

 CRect には CRect::Width() と CRect::Height() ってメンバ関数があっ
て、これを使えば横幅と高さが一発で出るから
……でもこれって、 right - left と bottom - top だよね
……あんまり便利じゃない?
少しだけ便利。あくまで少しだけ
じゃあそうだねぇ…… IDC_S_CANVAS の中央を四角く塗り潰してみましょ


void CAnimeDlg::OnBDraw() 
{
    // IDC_S_CANVAS の左上隅と右下隅を取得します。
    CRect cRect;
    ::GetClientRect( m_cCanvasStatic.GetSafeHwnd(), &cRect );
    // サイズを縮小します。
    cRect.DeflateRect
        ( cRect.Width() / 4
        , cRect.Height() / 4 );

    // ブラシとデバイスコンテキストを準備します。
    HBRUSH hBrush = ::CreateSolidBrush( RGB( 0, 0, 255 ) );
    HDC hDC = ::GetDC( m_cCanvasStatic.GetSafeHwnd() );

    // 四角形に塗り潰します。
    ::FillRect
        ( hDC
        , &cRect
        , hBrush );

    // ブラシを削除します。
    ::DeleteObject( hBrush );
}

うわ長!
……長いってだけで拒絶するのは悪いクセだよ?
べ、別に拒絶してるわけじゃないもん。えーっと……あ、よく見ると見た
ことあるのばっかだね
もちろん
最初の CRect とかのは今回のでしょ
これから描画する IDC_S_CANVAS のってことに注意してね。それと 
GetClientRect() ってとこも
 GetWindowRect() だとダメ?  IDC_S_CANVAS ってタイトルバーとかな
いからクライアントとウィンドウって同じじゃないの?
同じだけど、 GetWindowRect() だと画面の左上からの座標が入っちゃう
から面倒なんだよね。 GetClientRect() は
サイズだけなんだもんね。これに描くんだったら、 GetClientRect() の
方がいいわけだ。次の DeflateRect() ってのが初見だね
 CRect::DeflateRect() は、中心方向に縮小するメンバ関数。たとえば

    cRect.DeflateRect( 10, 10 );

ってすれば、上から 10 、左から 10 、右から 10 、下から 10 内側に狭
まります。あ、もちろん cRect の中の top とかがね
その引数に、 cRect.Width() / 4 ってことは、横幅の4分の1とかね
たとえば DeflateRect( 10, 10 ) した場合、左から 10 、右から 10 だ
から、横幅は 20 狭くなるわけ
ってことは横幅は、これまでの横幅の4分の1の2倍、つまり横幅の半分
を引いたのになるってことは……あー、結局半分になるわけね
そゆこと。そうひとつずつ考えてくとちょっとややこしいね……
その次はブラシ作ってデバイスコンテキスト取得してるね。これは
Ver 7.05 ( No.125 ) とかでのだからいいとして、次の FillRect() も初め
て見るの……だけど、これが四角く塗り潰す API ?
そう、第1引数のデバイスコンテキストの、第2引数の四角形を、第3引
数のブラシで塗り潰します
あれ? SelectObject() しなくていいの?
これはしなくていい API 。こういうのって API によって結構違うんだよ
ね、そういうのもこつこつ憶えていったり、憶えなくても〈色々ある〉って
ことに慣れておいて
そのためのデバイスコンテキスト編なんだもんね。んで、最後にブラシを
削除っと
うん、これまでの繰り返しがほとんどだから難しくはないと思うけど
質問!
はい火美ちゃん
 CRect は MFC のなんだから、他のも API じゃなくて MFC のを使うべき
なんじゃないんですかー?
だね。 FillRect() も CDC のメンバ関数として用意されてるし。でも、
もう API から MFC に乗り換えたり、ってできるでしょ?
そりゃ、ほとんど違わないから
だったら大丈夫。 API と MFC で違う時は両方とも解説載せるから
これは違わないからいいわけね。もひとつ質問
はい火美ちゃん
……これってホントに CRect の便利なとこ?
……さて最後のまとめ
うわ逃げやがった
もう一度構造体の話に戻るね。今はまだいいけど、最終的には古い C 言
語形式でも構造体を作れないとダメ
どゆこと?
普通に VC 使う時にはあり得ないけど、場合によっては古い C 言語形式
でプログラムを書かなきゃいけないときもあるから
…… VC 使わない時なんてあるの?
ってゆーかそういうのもいつか教えるから
げ、そなの? っつーかそれってこの講座の趣旨から外れてない?
いろんな開発環境を知ってこそのプロの VC 使い。実際、 VC マスターっ
ていうのは、プログラミングに関しては〈なんでもできる〉って思われるも

それに応えられなきゃダメってわけねー
ま、あくまでまだ先の話だけどね

/*
    Preview Next Story!
*/
……なんか、憶えたことは少ないのに、難しく感じるなー
範囲を広げたからね
範囲?
歴史とか、 C 言語と C++ 言語の違いとか
そういうのもやんなきゃいけない?
 VC じゃね。憶えなくていい言語もあるんだけど
たとえば Java とか?
というわけで次回
< Version 7.08 コンストラクタで初期化 >
につづく!
ま、 VC の道は険しいってことで
ゴールが見えないっていうのは辛いのよね……
 
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
RSSに登録
del.icio.us 登録する
Yahoo!ブックマーク 詳細を表示 users
livedoorクリップ 詳細を表示 livedoorクリップ ブックマーク数
はてなブックマーク 詳細を表示 はてなブックマーク ブックマーク数
 
このページは、Visual C++ 6.0を用いた C++ 言語プログラミングの解説を行う#pragma twiceの一コンテンツです。
詳しい説明は#pragma twiceのトップページをご覧ください。