掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板1

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧

No.7636

C++ classのprivate メンバーについて
投稿者---古い初心者(2007/07/03 09:27:14)


皆さんお世話になっております。
最近すごく思うのはC++ においてclassのprivate メンバーまで
公表しなければならないということです。
論理的に理解しにくいのではと思います。
classの内部に使っているいろいろものを全部(そしてclassのユーザに直接関係ない)さらさなければならないとはどうも変な感じをします。
皆さんのご見解をお伺いしたいです。
(回避策あれば、ご教授いただきたい)

どうぞ宜しくお願い致します。




この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:C++ classのprivate メンバーについて 7637 RAPT 2007/07/03 13:52:15
<子記事> Re:C++ classのprivate メンバーについて 7639 YuO 2007/07/03 14:43:20
<子記事> Re:C++ classのprivate メンバーについて 7640 たかぎ 2007/07/03 16:25:34
<子記事> Re:C++ classのprivate メンバーについて 7645 yoh2 2007/07/05 00:51:03


No.7637

Re:C++ classのprivate メンバーについて
投稿者---RAPT(2007/07/03 13:52:15)
http://blogs.wankuma.com/rapt/


それこそ、interface


この投稿にコメントする

削除パスワード

No.7638

Re:C++ classのprivate メンバーについて
投稿者---古い初心者(2007/07/03 14:42:41)


RAPT様
ご返事有難うございます。
>それこそ、interface
むー。「interface」ってその本意からすれば、「表面的なもの」で、
直接触れていいということでしょうね。直接触れない(または触れてはいけない)ものは通常「interface」とはしないでしょう。





この投稿にコメントする

削除パスワード

No.7639

Re:C++ classのprivate メンバーについて
投稿者---YuO(2007/07/03 14:43:20)


>classの内部に使っているいろいろものを全部(そしてclassのユーザに直接関係ない)さらさなければならないとはどうも変な感じをします。
>(回避策あれば、ご教授いただきたい)

とりあえず,Effective C++を読んで下さい。ほぼ答えが出ていると思います。


とりあえず書いてしまうと,
・実装自体は別のクラスにして,そのポインタ (不完全型へのポインタ) を持つクラスを公開する
・実装の記述のない抽象クラスを公開し,その実装クラスを生成する関数を別途公開する
といったような方法で回避します。


Scott MayersのEffective三部作はC++やるなら読んでおきましょう。
掲示板で質問するよりよっぽど効果的に知識を手に入れることができます。



この投稿にコメントする

削除パスワード

No.7641

Re:C++ classのprivate メンバーについて
投稿者---古い初心者(2007/07/04 10:47:32)


YuO様
いつもお世話になっております。
丁寧なご指導本当に有難うございます。
私的な理解ですが、基本はラッパーのようなものを造って、
目的classの宣言(通常*.hの形で提供)を直接に参照するのを回避するのですね。

書籍の情報も大変有難いと思います。特に二番目の本です。

さて、私もいろいろ試してやって見ましたが、
一つのnamespaceをclass本体(定義ファイル)の先頭に定義しておいて、
privateメンバーを全部class本体から抜き出して、
そのnamespaceに入れておけば、公表しなくてもOKになります。
(要はclassのユーザにpublicメンバーを宣言するヘッダファイルだけを渡せばいいようです)。

ただ、このような方法は"邪道"ではないかどうか分かりません。
確かに、interface classを造るのは通常みないです(例えばJavaもそうです)


またどうぞ宜しくお願い致します。



この投稿にコメントする

削除パスワード

No.7643

Re:C++ classのprivate メンバーについて
投稿者---YuO(2007/07/04 11:07:25)


>一つのnamespaceをclass本体(定義ファイル)の先頭に定義しておいて、
>privateメンバーを全部class本体から抜き出して、
>そのnamespaceに入れておけば、公表しなくてもOKになります。
>(要はclassのユーザにpublicメンバーを宣言するヘッダファイルだけを渡せばいいようです)。

その方法は使い物になりません。
複数インスタンスを作ったらどうなるか,試しましたか?



この投稿にコメントする

削除パスワード

No.7640

Re:C++ classのprivate メンバーについて
投稿者---たかぎ(2007/07/03 16:25:34)
http://www.kijineko.co.jp/


>(回避策あれば、ご教授いただきたい)

普通は、抽象クラスを使うかPimplイディオムを使うことになるかと思います。
ただ、それらの手法にはメリットもありますがデメリット(主にオーバーヘッド)もあります。隠蔽したいのが気分的な問題だけなら、デメリットの方が大きくなるかも知れないので要注意です。



この投稿にコメントする

削除パスワード

No.7642

Re:C++ classのprivate メンバーについて
投稿者---古い初心者(2007/07/04 10:53:24)


たかぎ様
ご教授ほんとうに有難う御座います。
>普通は、抽象クラスを使うかPimplイディオムを使うことになるかと思います。
>ただ、それらの手法にはメリットもありますが

抽象クラス=interface class(Java流の言い方)ですね。
ただ、先の返答にも書いているように、namespaceを利用してみたら、
一応目的達成したようですが、やはりinterface classのほうは普通ですね。
またご教授お願いできればと思います。






この投稿にコメントする

削除パスワード

No.7644

Re:C++ classのprivate メンバーについて
投稿者---たかぎ(2007/07/04 16:53:29)
http://www.kijineko.co.jp/


>抽象クラス=interface class(Java流の言い方)ですね。

必ずしもそうではありません。
抽象クラスというのは、一つでも純粋仮想関数を持つクラスのことです。
仮想関数は極力publicにしないで、
class A
{
  virtual int do_func(int arg) = 0;
public:
  int func(int arg) { return do_func(arg); }
};
のようにした方が何かと好都合です。

>ただ、先の返答にも書いているように、namespaceを利用してみたら、
>一応目的達成したようですが、

それがダメなことは、YuOさんが指摘済みですね。

>やはりinterface classのほうは普通ですね。

いや、Pimplイディオムの方が普通だと思いますよ。
こんな感じです。

// ↓ ここから
class A
{
  struct Impl* pimpl_;
public:
  A();
  ~A();
  int func(int arg);
};
// ↑ ここまでを公開

struct Impl
{
  int func(int arg) { ... }
};

A::A() : pimpl_(new Impl)
{
}

A::~A()
{
  delete pimpl_;
}

int A::func(int arg)
{
  return pimpl_->func(arg);
}




この投稿にコメントする

削除パスワード

No.7649

Re:C++ classのprivate メンバーについて
投稿者---古い初心者(2007/07/05 09:37:33)


たかぎ様

>いや、Pimplイディオムの方が普通だと思いますよ。
そうですか。最初に「Pimplイディオム」という言葉が分からなかったんで、調べようとしたら、親切にも具体な例を下さって、本当に有難う御座います。
面白いやり方ですね。
ただ、不明な点は一つあります。

たかぎ様written:
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// ↓ ここから
class A
{
struct Impl* pimpl_;
public:
A();
~A();
int func(int arg);
};
// ↑ ここまでを公開
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

このために構造体Implを公表しなければならいでしょう。
ところがint func(int arg)の本体がこのImplの中に含まれていますね。
私の誤解かもしれませんが、この例だと本来int func(int arg)を隠すことは目的ではないでしょうか。

またご教授いただければ幸いと思います。
どうぞ宜しくお願い致します。



この投稿にコメントする

削除パスワード

No.7650

Re:C++ classのprivate メンバーについて
投稿者---επιστημη(2007/07/05 09:51:30)
http://blogs.wankuma.com/episteme/


>このために構造体Implを公表しなければならいでしょう。

いいえ。



この投稿にコメントする

削除パスワード

No.7652

Re:C++ classのprivate メンバーについて
投稿者---RAPT(2007/07/05 11:01:28)
http://blogs.wankuma.com/rapt/


>>このために構造体Implを公表しなければならいでしょう。

すでに YuO 氏が述べられているとおりです。
>> 投稿者---YuO(2007/07/03 14:43:20)
>> ・実装自体は別のクラスにして,そのポインタ (不完全型へのポインタ) を持つクラスを公開する

> struct Impl* pimpl_;
識別子 Impl が何者かさえ示すことができていれば(ここでは構造体であることを明示)
そのポインタである、識別子 pimpl_ の宣言だけで充分であり、構造体 Impl の実装を
公開する必要はありません。

> ところがint func(int arg)の本体がこのImplの中に含まれていますね。
いいえ。func は Impl に含まれる関数を実行しているだけです。
Impl に含まれる関数等をポインタ経由で呼び出す場合は、実装を公開する必要はありません。



この投稿にコメントする

削除パスワード

No.7653

Re:C++ classのprivate メンバーについて
投稿者---古い初心者(2007/07/05 13:34:22)


RAPT様
丁寧なご解説よく分かりました。
試してみたらうまくできました!

ただ、このstructの処に namespaceに置き換えるだけで
いまの例で言えば
namespace Impl
{
int func(int arg) { ... }
};

にして、
classの実装ファイルの先頭に
using namespace Impl;
を付けば、structの宣言でさえ省けるのではないと思いますが、
なにか不都合なことでもあるのでしょうか。

またどうぞ宜しくお願い致します。



この投稿にコメントする

削除パスワード

No.7654

Re:C++ classのprivate メンバーについて
投稿者---επιστημη(2007/07/05 15:21:52)
http://blogs.wankuma.com/episteme/


>なにか不都合なことでもあるのでしょうか。

ダメダメです。
試せばわかります。




この投稿にコメントする

削除パスワード

No.7655

Re:C++ classのprivate メンバーについて
投稿者---古い初心者(2007/07/05 16:19:12)


επιστημη様
お世話になっております。

>ダメダメです。
>試せばわかります。

現に下記のように使っていますが。

----------def.c----------------
namespace private
{
short private1;
char private2;

int funPrivate(void)
{
..........

}


}

using namespace private

int pub::foo(void)
{
ini ret = funPrivate();

}

----------end def.c----------------


----------pub.h-------<ユーザーに公開>
class pub
{
public:
pub();
~pub();
int foo(void);
}

----------end pub.h----------------

これで下記のprivate的なものを公表しなくて済ませます。
short private1;
char private2;
int funPrivate(void);


どんな場合不都合になるのでしょうか。

もう少し詳しくご教授お願いできればと思いますが。









この投稿にコメントする

削除パスワード

No.7656

Re:C++ classのprivate メンバーについて
投稿者---επιστημη(2007/07/05 17:01:13)
http://blogs.wankuma.com/episteme/


>どんな場合不都合になるのでしょうか。

#include <stdio.h>

class Person {
  int age;
public:
  Person(int a) : age(a) {}
  void printAge() const { printf("I'm &d years old.\n",age); }
};

int main() {
  Person he(15);
  Person she(14);
  he.printAge();
  she.printAge();
  return 0;
}

Person から age をクラスの外に追い出してみてください。



この投稿にコメントする

削除パスワード

No.7657

Re:C++ classのprivate メンバーについて
投稿者---古い初心者(2007/07/05 17:55:35)


επιστημη様
感服、感服!
ご教授有難う御座います。
皆さんすごいですね。

結論:
1.namespaceを利用する場合
namespaceの中身はglobal的で、そのinstanceは唯一であるため、
class変数(static)よりも広範囲に共有される。

2.本当のclassメンバーではないので、classをconstructするついでに
メンバーとしての初期化はできない。

上述の二点で宜しいでしょうか。

また宜しくお願い致します。










この投稿にコメントする

削除パスワード

No.7662

Re:C++ classのprivate メンバーについて
投稿者---yoh2(2007/07/05 22:08:28)


「global的」とか、「本当のclassメンバーではない」とか以前に、namespace中で
宣言された変数はグローバル変数そのものです。
namespaceはクラスの代用品でも補助装置でもありません。

Cでは、グローバルに晒す名前は、他のライブラリ等とかぶらないように接頭子を付ける
習慣がありますが、その接頭子にあたるものが文法的に定められたものがnamespaceだと
考えてください。

例えば、Cでは、「ライブラリhogeのint型変数var」を定義したいとき、他のライブラリ
等と名前がかぶるのを避けるために、単純に「var」という名前にせず、
int hoge_var;
と宣言することが多いですが、C++では、namespaceを使って、
namespace hoge{
    int var;
}

とすることで、他のライブラリ等の識別子varとぶつからないようにすることができる、
と、ただそれだけのものです。(hoge::varという表記法で、hoge_varにアクセスできる
という意味ではありません。念のため。)
Effective C++あたり(じゃなくてD&Eだったかも)には、なかなか興味深いnamespaceの
応用例が書かれていたりもしますが、基本はこれだけです。


この投稿にコメントする

削除パスワード

No.7661

Re:C++ classのprivate メンバーについて
投稿者---たかぎ(2007/07/05 22:06:29)
http://www.kijineko.co.jp/


他の方が色々答えてくださったので、もう言うことはあまりないのですが...

先に示したPimplイディオムの例は、あくまでも雰囲気を掴んでもらうためのものでしたので、かなり省略しています。
特に、コピーコンストラクタとコピー代入演算子の定義は必須ですので、実際に使う場合はご注意ください。



この投稿にコメントする

削除パスワード

No.7645

Re:C++ classのprivate メンバーについて
投稿者---yoh2(2007/07/05 00:51:03)


> 最近すごく思うのはC++ においてclassのprivate メンバーまで
> 公表しなければならないということです。

回避策は出尽くした感がありますので、趣向を変えて、なぜこういった仕様に
なっているかを書いてみます。

前提1:
C++は、Cの、意味解析時に頼れる情報は翻訳単位の内容のみであり、他の
情報(例えば、他のコンパイル済みオブジェクト内の情報など)は利用しない、
という設計を引き継いでいる。
(exportに関してのみやや毛色が違いますが)

前提2:
C++のクラスはCの構造体を拡張する形で設計されているため、構造体と
同様に、インスタンスを作成する際に全体のサイズを知っておく必要
がある。非静的privateメンバ変数も他の非静的メンバ変数と同様に
構造体の1メンバと同じようにクラス内に配置されるため、全体のサイズ
にはprivateメンバの分も含まれる。

結論:
クラスインスタンス作成のためには、翻訳単位中でprivateメンバ変数の情報も
知っておく必要がある。

こんな感じでしょうか。
さらに突っ込んで、前提1と2はなぜそのような仕様になっているのかまで問わ
れると答に窮してしまいますが。

(ここから推測混じり)
実は、静的privateメンバやprivateメンバ関数などに関しては、必ずしも
クラス利用者に見えている必要があるわけではない(*)ので、これらに関しては
クラス定義部から分離できる仕様を作ろうと思えば実現できたはずです。
しかし、非静的privateメンバ変数をクラス定義部で公開しなければならない以上、
一部非公開にできたとしても片手落ちになってしまうため、特にそのような
仕様が作られなかったのではないかと思います。

(*)とはいえ、privateメンバ関数を隠すことを認めると、コピーコンストラクタと
operator=()をprivateにして、コピー不能なクラスを作る、などといった
テクニックが使えなくなりそう。


この投稿にコメントする

削除パスワード

No.7651

Re:C++ classのprivate メンバーについて
投稿者---古い初心者(2007/07/05 10:11:14)


yoh2様

素晴らしいご返答です!
目からうろこが落ちた感じです。

数日前に私が出した問題に
TH様は2回ほどご返事下さって
【[Re:深刻な問題を見つかった!】
(http://www3.realint.com/cgi-bin/tarticles.cgi?pointc2+7554)
それを見て
私はC++ではどうもclassの利用側はclassの宣言から
classの各メンバーの相対アドレスを取るのではないかと率直に感じました。
なんて原始的だなと思いました。

さすが、その通りですね。

本当に有難う御座います。
また宜しくお願い致します。






この投稿にコメントする

削除パスワード

No.7663

Re:C++ classのprivate メンバーについて
投稿者---yoh2(2007/07/05 22:48:51)


この手の細かい仕様については、入門書には書いていないことが多く、かといって、
上級者向けになると、今度は知っているのが常識とばかりに説明が端折られていたりします。
最も信頼できるのはISO/IECの原規格書(JISでも可)ですが、難解な上結構なお値段が
しますので、次善策として、リファレンス的な本の購入をお勧めします。
参考までに、私が使っている書籍を挙げると、C++では

ISBN:9784873111919 『C++ランゲージクイックリファレンス』
ISBN:9784873111964 『C++ライブラリクイックリファレンス』

Cでは、定番中の定番、

ISBN:9784320026926 『プログラミング言語C 第2版』(通称K&R)

です。K&Rはリファレンス本というよりは入門書に近く、やや不満はあるのですが、
これ以上のものを見付けられないもので。

また、規格書やリファレンス本には、詳細な仕様は記述されていますが、なぜそうなった
かの思想的な部分まではほとんど書かれていません。
そういった部分を解説している本もいくつか存在します。

C++なら、ISBN:9784797328547 『C++の設計と進化』(通称D&E) がおすすめ。
Cの場合、これまたそのものズバリというのは心当たりがありませんが、私は
ISBN:9784756116390 『エキスパートCプログラミング―知られざるCの深層』
を読んで、Cの哲学をそれなりに理解したつもりです。


この投稿にコメントする

削除パスワード

No.7664

Re:C++ classのprivate メンバーについて
投稿者---YuO(2007/07/06 00:34:36)


>最も信頼できるのはISO/IECの原規格書(JISでも可)ですが、難解な上結構なお値段が
>しますので、

INCITSがISO/IECの規格書と同等の規格書を出しています。
昔はISO/IEC 9899:1999とかまんまな名前で売っていましたが,最近はINCITS/ISO/IEC 9899:1999のように「INCITS/」がちゃんとついています。
# PDF中のタイトルはISO/IECのままですし,何かが違うわけでもなさそうです。

ANSI Electronic Standards StoreでISO/IEC 9899とかISO/IEC 14882とかを探すと一緒に出てきて,一桁違う値段 (現在$30) で買えます。
昔は$18とかで買えていたんですけどね……。
# 現在の$30 = 3800円程度でも,通常の書籍と変わらない値段だと思います。


この投稿にコメントする

削除パスワード

No.7666

お礼
投稿者---古い初心者(2007/07/06 10:04:03)


皆様
丁寧なご指導本当に有難う御座います。

透徹したご解説ばかりでなく、権威性の高い文献まで詳細にご紹介てくださって、本当に感謝の気持ちいっぱいで御座います。

これから一生懸命勉強しなければなりません。
今週でも本屋に行って見ます。

またどうぞご指導お願い致します。



この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    記事検索    ログ    タグ一覧





掲示板提供:(有)リアル・インテグリティ