プロが教える店舗&オフィスのセキュリティ対策術

いつもお世話になっております。
VC++初心者です。

現在、VC++6.0、MFCのソース修正で四苦八苦しています。
(コーディングするよりも。ソースを追うので苦労してます。)
(初心者の私が言うのも難ですが、オブジェクト指向云々言う前に
 ソースのif文節が異常に長かったり、3重以上ループが出てくると
 とても嫌になります、、、)

一般的(?)に、プログラミングは
手続き型プログラミングよりオブジェクト指向プログラミングが
開発効率がよい、と重宝されているようですが、
どうも納得できていません。
(その手の書籍を2,3冊読みましたが消化不良に終わっています。)

個人的には、手続き型プログラミングの方が好きです。
というのも、慣れているからかもしれませんが、
ソースが追いやすいし、見やすいと思います。

逆にオブジェクト指向プログラミングでは、
・継承されすぎると、基本クラスまで追うのが一苦労。
・インスタンスをつくってから、関数を呼ぶのが面倒な気がする。
 (手続き型なら関数呼び出しのみで済みます。)
・インスタンスをdeleteし忘れて、メモリを圧迫する危険がある。
 (ガーベージコレクションというものもあるようですが、
 どこで何を消しているか不安です。)
・ソースを追いにくい(慣れの問題なのでしょうか、、、)

そこでですが、
「手続き型は~~で大変だけど、オブジェクト指向ならこんなにすばらしい」
というような対比的に具体例を挙げて説明されている
書籍、サイトの紹介、または、よい助言を頂けませんでしょうか。

また、上記に伴い、
・手続き型で組んで失敗した例(オブジェクト指向型にすれば良かった例)
・オブジェクト指向型で組んで失敗した例(手続き型にすれば良かった例)
も宜しければ教えて頂きたく、お願いします。
(成功例のみよりも、失敗からの成功例を教えて頂けると嬉しいです。)

長くなりましたが、宜しければご教授下さい。

A 回答 (17件中11~17件)

#1 です。



#4 の回答はちょっとまずいかな・・・と思ったのでちょっと苦言を。

> C++言語はオブジェクト指向を熟知している人がオブジェクト指向になるように作ればオブジェクト指向プログラミングが可能な言語であって、必ずしもオブジェクト指向向きの言語ではありません。

それは、C++ に限らず、どんな言語にも言えることです。

> C言語からの継承もあってオブジェクトでは無い物を書けますし、MFCを使用する場合にはオブジェクトに収まらない領域にアクセスする必要が出てしまったりします。

「オブジェクト」という用語を何に対して使用しているのでしょうか?
「オブジェクトに収まらない領域」という言葉が何を言っているのか、いまいちわかりません。

> オブジェクト指向の意義と利点の理解には「オブジェクト指向でなぜ作るのか」が分かりやすくてお勧めです。

この本は、「間違ったオブジェクト指向」の本なので全くおすすめできません。
あまりにも「Java のオブジェクト指向」に偏りすぎているのも問題です。

オブジェクト指向でなぜ作るのか を買ってみました
http://d.hatena.ne.jp/minekoa/20080803/1217795027

> C++の言語使用の為でJavaでは呼べるように作ればインスタンスを作ら無くても呼べる。

C++ にもクラスメソッド (静的メンバ関数) はありますので、これは間違いです。

> C/C++ではメモリー管理がプログラマ責任になっているためです。
> インスタンスを配列に置き換えても同じことが言えます。
> オブジェクト指向だから…ではなくC++言語だから…です。

RAII を Java では実現できませんが、C++ では可能です。
C++ ではメモリ管理はプログラマが行うこともできますが、ふつうの C++ プログラマならスマートポインタを使います。
更に、Java など他の言語ではメモリ以外のリソース (入出力ストリームなど) の管理がプログラマ責任になっています。
しかし、C++ ではすべて言語に任せることができます。
オブジェクト指向には関係ないですが、C++ を見くびりすぎではないですか?

自分も Java は好きですが、Java の世界しか知らない人の意見に思えました。
    • good
    • 0
この回答へのお礼

ご回答、ありがとうございます。
(返信が大変遅れてすみません。)
再度のご教授、本当にありがとうございます。

>> C++言語はオブジェクト指向を熟知している人がオブジェクト指向に
>>なるように作ればオブジェクト指向プログラミングが可能な言語で
>>あって、必ずしもオブジェクト指向向きの言語ではありません。
>それは、C++ に限らず、どんな言語にも言えることです。
確かに、そうかもしれません。
現在、OOPでコーディングできるプログラミング言語は
増えてきましたが、その中でもRubyはOOPでスクリプト言語だから
とても開発効率がよい、という記事をどこかでみて
Rubyを使用しました。
しかしながら、OOPが理解できていない私には、
結局Rubyでも手続き型のように組んでしまうのです、、、

また、#4さんがお薦めしていただいた本に対する
ご意見、ありがとうございます。
一方、OOPが理解していない私に
良心的に答えて頂いた#4さんにも感謝をしております。
しかしながら、OOPの理解に混乱する原因はここにあると思います。
OOPを理解していると自負されている方は数多くいらっしゃることは
言うまでもなく、OOPについて説明している書籍はかなりあります。
しかしながら、説明するキーワードは共通していても、
説明内容が各々で発散しすぎていると感じております。
(あくまで私の見解なのですが、もし、OOPを理解している人達が、
 ある同じ問題を各々でOOPでコーデングするれば、
 限りなく一意に近いソースコードに成ると思いますが、
 どうなのでしょうか。
 なるのであれば、なぜ説明が収束しないのか不思議です。)

OOPを理解していない私には、どの本が良書で悪書か判断できません。
やはり、良書と呼ばれるものをひたすら読んで、自分に理解できる
レベルか否か判断して、駄目なら、他の良書と呼ばれるものを
あさるしかなさそうです。

やはり、OOPを理解する道は険しそうです。

お礼日時:2009/08/17 02:19

個人的な意見になりますが、すべては作成する人次第です。


どんなに目的に適している言語を使用していても、分かりやすく作れないひとはたくさんいます。その言語の理解力にかかっているということになります。

大雑把な説明でいうと(かなり大雑把ですけど)
Cの場合見やすくするために機能別に関数にしたりしていますが
C++で行う場合クラスにすることでまとめます。

Cの場合、関数間で共有する変数は外部変数として定義しなければなりませんが、C++の場合、クラスにすることでクラス内の関数のみ参照出来るようにできます。
    • good
    • 0
この回答へのお礼

ご回答、ありがとうございます。
(返信遅れてすみません。)

>個人的な意見になりますが、すべては作成する人次第です。
初心者の私が言うのも苦しいですが、本当にそう思います。

現在、先人が残したMFCのソースを修正していますが、
OOP、非OOPを語る以前の問題で、1つのクラスが500行以上あったり
3重、4重ループがあったり、深い階層のif節があったりします。
(そして、コメントはほとんどなく、何をしているか理解するのに
 本当に苦労しています。)

アドバイス頂いたその大雑把な説明が私には
とても理解しやすい、というよりも、イメージしやすいです。
これからの自分で修正するOOPソースには、
今まで関数でまとめていた事を
クラスとしてまとめようと思います。
(OOP設計の方向がつかめたような感じです。)
しかしながら、適切なクラス設計は大変なんでしょうけど、、、

お礼日時:2009/07/29 02:28

> ・インスタンスをつくってから、関数を呼ぶのが面倒な気がする。


>  (手続き型なら関数呼び出しのみで済みます。)

解説書はインスタンスを1つしか作っていないから、そのメリットを受けられないんだと思います。

構造体型の変数を2つ3つ作るのと似たようなものではあるんですけど、
どの変数(オブジェクト)に対して処理をするか、というのを、
手続き型ではいちいち引数で指定しないと行けないですからね。
OOPでは「自分自身」が対象ですから、指定する必要はありません。

また、すでに出ていますが、関数を呼び出すときに引数を減らせるメリットが出ます。
OOPにすると、そのオブジェクト内でグローバルに使える変数(プロパティ)がありますから、
それを使っている限り引数を省略できます。
(メソッドの数が増えたりしますが(^^;)

> ・継承されすぎると、基本クラスまで追うのが一苦労。
> ・ソースを追いにくい(慣れの問題なのでしょうか、、、)

ソースを追うどうかは、既存(完成した)ライブラリのソースを追わないのと同じだと思います。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
(返信が大変遅れてしまい、申し訳ございません。)

>手続き型ではいちいち引数で指定しないと行けないですからね。
>OOPでは「自分自身」が対象ですから、指定する必要はありません。
>また、すでに出ていますが、関数を呼び出すときに引数を減らせるメリットが出ます。
そうですね。手続き型ですと、引数が膨大になる可能性がありますね。
(良いかどうかわかりませんが、引数を減らすように、いつも中間
ファイルを作成していました。)
OOPですと、オブジェクト内でオブジェクト自身が持つ変数ならば、
オブジェクト内に限り、グローバル変数のようにどこでも呼べますよね。
(この認識は、OOPを理解する上で正しいのでしょうか?)

>ソースを追うどうかは、既存(完成した)ライブラリのソースを
>追わないのと同じだと思います。
ご指摘のとおり、ライブラリのソースは追いません。
というよりも、追った事がございません。
その理由は、MSDNを始めとするサイトで、
ライブラリ関数の説明、使用例が紹介されているからだと思います。
しかしながら、現在私の置かれている状況は、簡素な仕様書、
及び、コメントの少ないソースコードのみです。
そうなると、何をしているのかソースを追う事になるので、
今はそれがとても辛いです。
(泣き言になってしまい、すみません。)

アドバイスありがとうございました。

お礼日時:2009/08/17 00:29

C++言語はオブジェクト指向を熟知している人がオブジェクト指向になるように作ればオブジェクト指向プログラミングが可能な言語であって、必ずしもオブジェクト指向向きの言語ではありません。


C言語からの継承もあってオブジェクトでは無い物を書けますし、MFCを使用する場合にはオブジェクトに収まらない領域にアクセスする必要が出てしまったりします。

その点ではJavaの方がオブジェクト指向の利点を感じやすいです。

オブジェクト指向は構造化プログラミングの欠点を補うために発明されたと思っています。
で、構造化プログラミングの欠点は小規模、少人数、短期間の開発では感じにくい(というか、ほとんど感じない)のです。
大規模、大人数、長期間の開発になったときに、安全性・確実性を担保できるだけでも物凄いメリットなのですけどね。

オブジェクト指向の意義と利点の理解には「オブジェクト指向でなぜ作るのか」が分かりやすくてお勧めです。

その他、言語仕様やツールの問題でオブジェクト指向の問題では無い点もあります。
>・継承されすぎると、基本クラスまで追うのが一苦労。
 そもそも基本クラスを追う必要が(本来なら)無い。

>・インスタンスをつくってから、関数を呼ぶのが面倒な気がする。
 C++の言語使用の為でJavaでは呼べるように作ればインスタンスを作ら無くても呼べる。

>・インスタンスをdeleteし忘れて、メモリを圧迫する危険がある。
 C/C++ではメモリー管理がプログラマ責任になっているためです。
 インスタンスを配列に置き換えても同じことが言えます。
 オブジェクト指向だから…ではなくC++言語だから…です。

>・ソースを追いにくい(慣れの問題なのでしょうか、、、)
 VC++2005/2008やEclipse、NetBeansIDEなどのクラスエクスプローラーが充実しているIDEだと楽に追えます。
 互換性の都合でVC++6と2005を併用していますが、2005に慣れた今ではVC++6はあまり使いたく無いです。
 (VC++6だとソース追っかけるのが面倒なので)
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
(大変遅い返答になり申し訳ございません。)

>C言語からの継承もあってオブジェクトでは無い物を書けますし、
>MFCを使用する場合にはオブジェクトに収まらない領域にアクセスする
>必要が出てしまったりします。
>その点ではJavaの方がオブジェクト指向の利点を感じやすいです。
私の場合、MFCもJavaも熟知しておりませんので、恐縮ですが、
オブジェクトに収まらない領域にアクセスする領域とは
どのような事でしょうか。
また、Javaを使用しましたが、オブジェクト指向を理解していなかった
ので、手続き型のようにコードを書いてしまい、結局その利点を
感じることは出来ませんでした。

>大規模、大人数、長期間の開発になったときに、
>安全性・確実性を担保できるだけでも物凄いメリットなのですけどね。
このことは、私の読んだ参考書に同じようなことが書かれておりました。
私にはそのような大規模なものに取り組んだことがない為、
実感できていないのかな、と思っております。

お礼日時:2009/08/17 00:06

ちなみに、



オブジェクト指向⊂手続き型

ですよね。一般的には。
対立概念ではないと思います。

>個人的には、手続き型プログラミングの方が好きです。

それならそれで良いのでは?
他の人が「いい」と言うから、と言う理由で盲信しなきゃいけない、って事は無い筈ですけれども。本来なら、ですね。
まあ、会社で「こう言う形式でこの言語で書いてくれ」と言うガイドラインがあるなら別ですが、個人的レベルでは

「××と言う形式を好きにならなきゃいけない」

って事は無いでしょう。
懐疑的で良いのではないですか?

>「手続き型は~~で大変だけど、オブジェクト指向ならこんなにすばらしい」
>というような対比的に具体例を挙げて説明されている
>書籍、サイトの紹介、または、よい助言を頂けませんでしょうか。

へそ曲がりなんで(笑)、逆を挙げてみましょうか(笑)。
実はyuki7091さんの「感覚」の方が正しいのかもしれませんよ(笑)。

Bjarne Stroustrup Interview about C++ :
http://hp.vector.co.jp/authors/VA000092/jokes/st …

これは冗談ですが、自虐的ジョークに思えます。と言うのも「その手の批判がある」ってのは事実だから、でしょう。
他にオブジェクト指向に付いては

バベル案内:
http://www.aoky.net/articles/steve_yegge/tour_de …

いいアジャイルと悪いアジャイル:
http://www.aoky.net/articles/steve_yegge/good_ag …

なぜArcはとりたててオブジェクト指向でないのか:
http://practical-scheme.net/trans/noop-j.html

Rees Re: OO:
http://practical-scheme.net/trans/reesoo-j.html

辺りに色々書かれているのでご覧ください。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
(返信遅れてすみません。)

Bjarne Stroustrup Interview about C++ :
http://hp.vector.co.jp/authors/VA000092/jokes/st …
教えていただいた上記の記事から以下を抜粋します。
「プロジェクトの設計と、C++プロジェクトの設計の違いに気付いた
ことはありませんか。 C++プロジェクトの設計段階にかかる時間は、
3倍です。 継承すべきもの、すべきでないものを正確に決めるためです。
それでも、判断を間違えます。 」

抜粋した記事のように、(慣れもありますが)
私には、オブジェクト指向型の方が設計には時間がかかるとは
思います。
(使う分には便利でいいのですが、、、)

非OOP設計だと大規模なソースを書くには好ましくない、
とどこかの記事で見ましたが、質の悪いOOPソースの
方がよっぽどタチが悪いような気がします。
(漠然とした言い方でしか表現できなくてすみません。)

間違ったOOP設計をしない為に、UMLも昔勉強しましたが
OOPが理解不十分なので、UMLも未消化に終わっています。
やはり、OOPを理解する為には、デザインパターンやUMLも
必要となり、私にはかなりOOPの理解する敷居は高いと感じます。

ちょっと脱線気味になりましたが、悔しいので
今はOOPがまだ完全に理解できなくても
理解できるように勉強を続けていきたいと思います。

お礼日時:2009/07/29 02:04

うーん。

大前提となるところに大きな問題があると思うんだが。

MFCは、「オブジェクト指向」じゃないだろう(笑)、という突っ込みは。まぁ脇に置いて。MFCをもって「オブジェクト指向は難しい」といわれてもなぁ……。そうじゃなくて、ただ単に「MFCが難しい」というだけと思うんだが。

MFCは、Cからのユーザーの取り込みを重視していて、旧来のWindows APIに毛が生えた程度のラッピングクラスとリソースを組み合わせてなんとかごまかしている。オブジェクト指向のフレームワークの中で、「もっともオブジェクト指向的でないもの」だろうと思う。MFCの難しさの大半は、「MFCだから」であって、「オブジェクト指向だから」ではないだろう。

どうも、見たところ、C++をもって「オブジェクト指向は……」といっていると思うんだが、C++は、オブジェクト指向言語だろうか? 「オブジェクト指向にも対応した言語」であって、これをもってオブジェクト指向と思われてしまうと、どうなんだろう。

もう少し、他の言語も見てみるといいと思うんだが。オブジェクト指向というものを深く知りたいなら、まずC++から離れなさい。と助言するしかないだろう。せめて、JavaかC#か、あるいはRubyあたりを勉強すれば、がらりと印象は変わると思うんだが。

>「手続き型は~~で大変だけど、オブジェクト指向ならこんなにすばらしい」

うーん。例えばだが、シンプルなウインドウが1枚あって、マウスでドラッグしたりリサイズしたりでき、クローズボックスをクリックすると終了する、そんなプログラムを作るとしよう。構造化言語(なんでもいい)で、どのぐらいのコーディングが必要だろうか。例えばJavaなら、まぁ実質5行も書けば完成する。どっちが楽だろう?
    • good
    • 0
この回答へのお礼

ご回答、ありがとうございます。
(返信遅れてすみません。)

>MFCは、「オブジェクト指向」じゃないだろう(笑)、
>という突っ込みはまぁ脇に置いて。
技術力が低くてすみません。
突っ込まれても、「自分は変な事いっているの?」っていう状態です。
私の認識ではMFCはAPIとC++が合体したような言語だと思っていますが
間違いなのでしょうか。

>JavaかC#か、あるいはRubyあたりを勉強すれば、
>がらりと印象は変わると思うんだが。
私自身、JavaもRubyも勉強程度には経験はございます。
自作のJavaやRubyのソースを見ると気持ち悪いのです。
原因は、せっかくのオブジェクト指向言語なのに手続き型っぽく
自分ソースが組まれているからです。
だから、言語ではなく、やはりソースの組み方が重要だと思いますが
如何でしょうか。

せっかく、回答頂いているにも関わらず、
その回答に対して更なるたくさんの質問をしてしまった
無礼をお許し下さい。

お礼日時:2009/07/29 00:12

C++ で OOP をすることの是非はこの際置いておくとして、まず気になった点から。



>・継承されすぎると、基本クラスまで追うのが一苦労。
これは、「間違った」オブジェクト指向プログラミングが原因である場合が多いです。
オブジェクト指向に「間違ってる」とか「間違ってない」とかあるの?というある種危険な方向に進んでしまいがちな話題ですが、あえてこの表現を使いました。

>・インスタンスをつくってから、関数を呼ぶのが面倒な気がする。
非 OOPL の場合、関数の引数が増えがちで、見にくくなりやすいという問題がありますよね?
また、構造体にまとめたとしても、その構造体をつくる必要があります。
これ、インスタンスをつくるのとどちらが面倒ですか?同じだと思います。

>・インスタンスをdeleteし忘れて、メモリを圧迫する危険がある。
OOP の話ではなく、C++ の話になってしまうのですが、RAII というイディオムが C++ にはあります。
このイディオムを使用した「スマートポインタ」というクラスを使用することで、delete し忘れが防げます。
また、構造化プログラムでもメモリを動的確保・解放することはよくありますよね?malloc とか free とか。
他にも、FILE 構造体を操作する fopen とか fclose とか。
こういったものが、RAII イディオムを使用することで、確実に解放忘れがなくなります。
OOP の利点ではないですが、クラス (とテンプレート) を使うことの大きな利点になるのではないでしょうか。

で、書籍ですが、OOP 自体なら「デザインパターンとともに学ぶオブジェクト指向のこころ」という本がおすすめです。
そして、その後に「アジャイルソフトウェア開発の奥義」や「Java 言語で学ぶデザインパターン入門」、「パターン指向リファクタリング入門」に進むのがいいと思います。

と、ここまで書いたのですが、C++ という言語は OOP だけでなく、様々なパラダイムをサポートするマルチパラダイム言語です。
個人的には、OOP だけに偏った学び方はあまりよくないと考えています。
ですので、C++ In Depth シリーズの本をおすすめします。
Exceptional C++ や、Modern C++ Design などです。
また、テンプレートに関しては、C++ テンプレートテクニックという日本人が書いた本がありますので、そちらもおすすめしておきます。

で、手続き型で組んで失敗した例、ですか・・・
自分自身、初めてまともに触った言語が Java なので、手続き型と意識して何かを組んだことがないのですよね・・・
オブジェクト指向で組んで失敗した例ならいくつもあります。でもそれは手続き型にすればよかった、ではなく、オブジェクト指向に対する理解が浅かった、と考えています。
例えば、「問題領域から名詞を抽出し、クラスの候補とし、動詞を抽出し、メソッドの候補とする」という設計方法(?)があるのですが、これは実はあまりよろしくない。
詳しくは「オブジェクト指向のこころ」を読んでいただくとして、こういった「間違った」説明が溢れているのがオブジェクト指向の欠点、ですかね。

以上です。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
(返信遅れてすみません。)

・多重継承について
 ご指摘して頂いたように、多重継承は間違ったOOPということは
 どこかで聞いた覚えがあります。その間違ったOOPをしないために
 Javaは多重継承ができなかった、と記憶しています。
 (うろ覚えですみません)
 しかしながら、多重継承でも正しいOOPというものがあるのでしょうか。
 正しいOOPがあるからC++では多重継承を許可しているのでしょうか。
 また、何を持って正しい、正しくないかが分かっていないので、
 どんどん「分からないスパイラル」に陥ってしまいそうです、、、

・インスタンスをつくってから、関数を呼ぶのが面倒
>非 OOPL の場合、関数の引数が増えがちで、
>見にくくなりやすいという問題がありますよね?
ご指摘頂いて、そういえばそうだなぁ、と思いました。
だからといって、OOPも非OOPでも面倒なのは同じなら、
慣れている非OOPでもいいのかな、とも思ってしまいます。
(既存のソースがOOPで組んであるなら、そのソース修正の際は
 不慣れでもOOPで組もうと思います。)

・インスタンスをdeleteし忘れて、メモリを圧迫する危険がある。
RAII、スマートポインタというのを初めて知りました。
(この時点で、私の技術レベルを推し量られてしまいますね。)
とても便利そうなので、この2つを早く使えるようにしようと思います!

ご紹介していただいた書籍の
「デザインパターンとともに学ぶオブジェクト指向のこころ」
を今度書店で見てみようと思います。
この本で何とかOOPの有用性が分かって
使いこなせればいいな、と思います。

この度は、長文にわたる回答をして頂き、本当にありがとうございました。

お礼日時:2009/07/28 23:57

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!