スポンサーサイトデータメンバを公開するのも、時には方便

Home > 2008-07 /  > This Entry 2007-09 / 実装技術 > This Entry [com : 6][Tb : 0]

2007-09-11

純粋な構造体を除き、データメンバは常に非公開にするのは、クラス設計のイロハのようなものです。しかし、時には禁忌を犯してみるのもよいのかもしれません。それは次のような理由からです。

データメンバを非公開にしている以上、オブジェクトの初期化は必ずコンストラクタによらなければなりません。しかし、コンストラクタを用いて動的に初期化する場合、そのオブジェクトを ROM に配置することは不可能になります。

オブジェクトの宣言時に const 修飾子を付けて静的記憶域期間を持たせる場合、おそらくはそれが ROM に配置されることを期待してのことでしょう。だとすると、動的な初期化しかできないのは都合が悪いことになります。

ところで、C++ の次期標準規格に導入される予定の std::tr1::array クラステンプレートは、データメンバが公開されています。ですから、

std::tr1::array const a = { 1, 2, 3 };

のように初期化子を与えて、静的に初期化することが可能です。このクラステンプレートは struct を使って定義されますが、構造体と呼ぶには、コンテナの要件を満たすメンバ関数が一通り用意されており、やや無理があります。

データメンバが公開されていないクラスには class を、データメンバを公開しているクラスには struct を用いるなどして、一見してそのクラスの持つ性質が分かるような工夫をするのもよいかと思います。

Comment

M : 2007-09-12(Wed) 01:04 URL edit
上記のような初期化ができるのは、arrayのデータメンバが公開されているからというのもありますが、arrayがPOD型の条件を満たしているからでもあります。
つまりデータメンバの公開だけでは足りず、コンストラクタがないこと、プライベートメンバがないこと、仮想関数がないこと、基本クラスがないこと、といった条件も満たされている必要があります。
たかぎ : 2007-09-12(Wed) 09:33 URL edit
コメントありがとうございます。
確かにやや言葉足らずでしたね。

まず、初期化子を用いての初期化は、必ずしも POD である必要はありません。array の要素が std::string とかでも構いませんから。
次に、ROM に配置できるかどうか、すなわち静的初期化だけで済むかどうかについては、POD であることが必須です。

struct A {};
struct B : A { int a, b; };

のような場合なら、静的初期化だけで済むような気もしますが、仕様上は無理ですし、実際、初期化子で初期化しようとするとエラーになりますね。
uskz : 2007-09-12(Wed) 10:07 URL edit
標準の言葉で言えば,arrayがaggregateの条件を満たしているから〜ですね.(8.5.1)
たかぎ : 2007-09-12(Wed) 11:15 URL edit
初期化子で初期化できるのは集成体(aggregate)ですね。
ところで、C の集成体は共用体を含みませんが、C++ の集成体は共用体を含みますね(少なくとも、8.5.1はそう読み取れます)。この辺は混乱しそうです。

もうひとつ。集成体の初期化子はメンバを記述した順に並べますが、途中にアクセス指定子が入ると、メンバのアドレスが昇順になることが保証されないのも罠ですね。(9.2)

struct A
{
public: int a;
public: int b;
};

と書くと、&a < &b とは限らなくなるようです。
M : 2007-09-13(Thu) 00:55 URL edit
なるほど、初期化子で初期化するためのPOD型である必要はないのですね。勉強になりました。
ジョブ+アイデム@歌姫 : 2007-12-29(Sat) 11:07 URL edit
記事を読ませて頂いて大変勉強になりました。
これからもどんどんすばらしい情報を配信してくださいね!
楽しみにしております。
Post a Comment









管理者にだけ表示を許可

Trackback

http://cppemb.blog17.fc2.com/tb.php/105-a6461fa7

C++と組み込み環境 | Page Top▲

New >>
保守投稿
<< old
本ブログの記事をまとめ始めています。
ブログ内検索
RSSフィード