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

 今,c++で色を表すクラスを作っています.
 色とはいっても,RGBやXYZなどいろいろな色がありますよね?もし,「各成分の合計を求める」なんて言う関数を作ろうと考えるとすると(必要ないですが^^…)RGBに対しても,XYZに対しても,というように2つ以上作るのは面倒です.そこで,n成分を持つ色のクラスというものを作って,そのクラスを継承して,RGB, XYZなどを表せないかと考えました.
 つまり…
class color3{
double data[3];
~~~~~~
};

class rgb : public color3{
~~~~~~
};

class xyz : public color3{
~~~~~~
};
(実際color3はtemplateクラスで,double data[3]もポインタを使って要素数を変更できるようにしています.)

もちろんこの方法で正常に動いていますが….これではrgbクラスの変数cを宣言して,成分を参照するときに,赤色ならc.data[0],緑色ならc.data[1]というように,data[~]で参照しなければなりません.しかし,これでは見にくいと思っています><.できるなら赤色ならc.r, 緑色ならc.gというように参照したいです.もちろん派生クラスの中にdouble r, g, b; と宣言すればいいのですが…
.そうしてしまうと,一番最初の目的が達成できません.ポインタを使ったり,メンバの値を取得する関数(getR(), getX()みたいな…)を作れば解決できますが,この方法を使うと*(c.r), c.r()のような参照をしなければならず,「c.r」というようなきれいな参照はできません.贅沢を言っているようではありますが.c.rと表せるようなクラスの設計の仕方はあるでしょうか?
 現在ぼんやりと考えているのは
class color3{
double data[3];
~~~~~~~
}:

class rgb : public color3{
double &r = data[0];
double &g = data[1];
double &b = data[2];
~~~~~~
};

class xyz : public class3{
~~~~~~
};

のように,参照変数を使えないか,と思っています.もちろん上の方法ではコンパイルエラー
となりましたが><

 質問が長くなってしまいすいません><
 よろしくお願いします.

必要ないかもしれませんが参考までに…
【環  境】MaxOS 10.6
【言  語】c++
【開発環境】Xcode
【 レベル 】プログラミング歴6年 c歴4年 c++歴1年の大学1年です

A 回答 (3件)

これ↓ではいかがです?



#include <iostream>
using namespace std;

class color3{
public:
double data[3];
};

class rgb : public color3{
public:
double &r;
double &g;
double &b;
rgb() : r(data[0]), g(data[1]), b(data[2]) {}
};

int main() {
rgb x;
x.data[0] = 1.23;
cout << x.r << endl;
x.g = 4.56;
cout << x.data[1] << endl;
}
    • good
    • 0
この回答へのお礼

 試してみると,上手くいきました(^^)/
 コンストラクタを使うって言う感覚が頭になかったです><
 これでわかりやすく表せそうです^^
 ありがとうございました

お礼日時:2011/03/23 23:21

class color3


{
public:
 virtual double* data() = 0;
 double& data(int idx) { return data()[idx]; }
};

class rgb : public color3
{
public:
 double r, g, b;

public:
 virtual double* data() { return &r; }
};

class xyz : public color3
{
public:
 double x, y, z;

public:
 virtual double* data() { return &x; }
};

これでも大体要求を満たせるのではないかと思うのですが、いかがでしょうか。
    • good
    • 0
この回答へのお礼

 仮想メンバを使うって言う手があったんですね.
 1度試してみます^^
 回答ありがとうございました

お礼日時:2011/03/27 02:43

クラスを設計するとき、特に何かを継承するとき、「本質的な部分は何か?」というのを常に意識しなければなりません。



この例だと、そもそも、color3 というクラスは何者でしょうか?
色を表す基底クラスですか?
だとすると、どのあたりが「色」の性質なのでしょう?

もし、本当に「色」を表すものなら、色としての本誌的な情報を持っているはずなので、これを継承する rgb などのクラスと相互に変換できる必要があるでしょう。

もしかしたら、これは、単なる「N個の数値に関するいろいろな演算をまとめた」クラスかもしれません。
この場合だと、いろいろな色を表すのに共通して使うかもしれませんが、「色」ではありません。
この場合、直接継承するのではなく、メンバーとして持つほうが間違いがありません。

calss color3 // たぶん、名前は変えた方がいい
{
};

class rgb
{
private:
color3 basicList;

public:
double r;
double g;
double b;
}

です。

また、本当は、「色」という機能を持った場合、r の値を変更するといろいろと副作用があるはずです。
全体としての明るさが変わるとか。
そういうつじつまあわせを確実に行うためには、r, g ,b を public: なメンバーにするよりも、getter や setter 経由で使う private: なメンバーにしておく方が安全です。

また、共通の「色」のクラスから継承したとしても、r, g b, というものをあからさまにしてしまう時点で、x, y, z とのインターフェイスは、完全に同じというわけにはいきません。

このあたり、何を本質的とするか、何を固有のものとするかというのも考えるべきところです。
    • good
    • 0
この回答へのお礼

 やはり要素はprivate:で宣言しておいた方が,安全なんですね.いつもめんどくさがってpublic:で宣言してしまうので気をつけなければなりません><
 回答ありがとうございました

お礼日時:2011/03/27 02:21

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