グローバル空間を自由にするために、クラスで必要とされる定数はどこに配置しますか?

まず、プログラムを書く方法を知っているので、私はそれに助けを求めていません。しかし、私は問題のコピーを貼り付けているので、あなたは割り当てが何を伴うかを見ることができます。私の質問は、すべてをグローバルにすることを避けるために、どこに変数を配置するのかを具体的に目指していますか?

割り当て

月、日、および年を格納する整数データメンバーを持つDateというクラスを設計します。クラスには、新しいDateオブジェクトが作成されたときに日付を設定できるようにする3つのパラメータのデフォルトコンストラクタが必要です。ユーザーが引数を渡さずにDateオブジェクトを作成した場合、または渡された値のいずれかが無効な場合は、2001年1月1日のデフォルト値である2001年1月が使用されます。クラスには、次の形式で日付を出力するメンバー関数が必要です。

3/15/10
March 15, 2010
15 March 2010

質問

1)教師はコード内でマジックナンバーを使わないように指示していたので、最初の質問はデフォルトのコンストラクタの実装に関するものです。

// These are outside the class.
#define DEFAULT_MONTH 1
#define DEFAULT_DAY   1
#define DEFAULT_YEAR  2001

// This is inside the class definition.
Date(int month = DEFAULT_MONTH, int day = DEFAULT_DAY, int year = DEFAULT_YEAR);

これは正しいです?

2)クラスは月の名前を保持する string オブジェクトの配列にアクセスする必要があるため、月の代わりに月の名前を表示する日付出力に使用できます。数値の月( switch に使用される)の enum を使用しました。

const enum MONTH_IDS { JANUARY = 1, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY,
    AUGUST, SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER };

const string MONTH_NAMES[NUM_MONTHS] = { "January", "February", "March",
    "April", "May", "June", "July", "August", "September", "October",
    "November", "December" };

この部分の質問は、どこに置くのですか?

Some things I can't do... I am not allowed to use static class members yet because that will be covered in the next chapter. We also have not gone over pointers, but we can use references.

ご協力いただきありがとうございます!

インストラクターに尋ねるが、彼は町外にいて、明日の予定だ。

5
静的なローカル変数を使用することはできますか?
追加された 著者 Robᵩ,
静的メンバーではなく、静的ローカルです。私の今後の答えを見てください。
追加された 著者 Robᵩ,
名前空間の下に定数を置くことができます。定数:: MY_CONST;またはこのようなものです。
追加された 著者 FailedDev,
@ロブ私は静的メンバーを認識していますが、第9章までは使用できません。
追加された 著者 user898058,
@FailedDev私はそれがまた行く最善の方法かもしれないと思っていた。
追加された 著者 user898058,

3 答え

1)定義が醜いです。 static const int メンバーは私がやることですが、できません。列挙型はどうですか?

struct Date {
    enum Constants {
        DEFAULT_YEAR = 2001,
        DEFAULT_MONTH = 1,
        DEFAULT_DAY = 1,
    };


    Date(int month = DEFAULT_MONTH, int day = DEFAULT_DAY, int year = DEFAULT_YEAR);

};

2)静的メンバー配列は必要なものだけです。しかし、静的なローカル変数を使うことはできません:

struct Date {
    std::string MonthToString(enum MONTH_IDS m) {
        static const char *monthNames[] = {
            "January", "February", "March", "April", "May", "June",
            "July", "August", "September", "October", "November", "December" };
        if(m >= sizeof(monthNames)/sizeof(monthNames[0]))
            return std::string("Unknown");
        return std::string(monthNames[m]);
    }
};
4
追加された
@ephaitch:私の答えの例#2を参照してください。変数 monthNames は静的ローカル変数です。
追加された 著者 Robᵩ,
静的なローカル変数を実装する方法の例を教えていただけますか?それらをコンストラクタ自体に配置しますか?またはコンストラクタによって呼び出されたメンバ関数内にありますか?あるいは全く異なる実装。
追加された 著者 user898058,
私は再びそれを見て、MonthToStringが関数であることを認識しました。ありがとう!
追加された 著者 user898058,

グローバル名前空間を汚染することなく定数を定義したい場合は、名前空間を持つグローバルまたはクラススタティックを使用するのが最も良いオプションの2つです。あなたがクラス静的を使用することはできないと言うので、私は名前空間を持つグローバルの例を示します:

// .h file
namespace mynamespace {
    extern const int foo;
};

// later, in a .cpp file
namespace mynamespace {
    const int foo = 42;
};

この変数には、 mynamespace :: foo 、または namespace mynamespace; (ヘッダーファイルでは避ける)または foomynamespace ネームスペース内の他の関数に追加します。 mynamespace 名前空間を要求している(またはそうでなければ認識している)人がアクセスできるだけなので、グローバル名前空間(およびこれに関係する不幸な名前の衝突)を汚染することはありません。

数値の場合、 enum は別の選択肢です。

class foo {
  enum { CONST_FOO = 42, CONST_BAR = 24 };
};

これらの値はコンパイル時の定数です。あなたはそれらのアドレスを取ることはできません(しかし、それらは const 変数より少し速くなります)。これは整数値に対してのみ使用できることに注意してください。

関数の統計は別の良いオプションです:

void myclass::somefunction() {
    static const char *monthNames[] = { "JANUARY", ... };
    //...
}

しかし、配列は実装に深く組み込まれているため、「マジックナンバー」よりもはるかに優れていません。

あなたの場合、私は enum または(非整数の)クラスの統計を使うのが一番良いと思います。あなたの教授がクラススタティックの使用を任意に制限している場合は、変数をグローバルスコープ(おそらくネームスペース内)に置き、許可されていればクラススタティックにしたというコメントを追加してください。

2
追加された
詳細な説明をありがとう!
追加された 著者 user898058,

static const のメンバ(または地方)を実行できない場合は、すべてを名前空間に入れることができます:

宣言:

namespace ephaitch {
    extern const int Date_default_month;
    extern const int Date_default_day;
    extern const int Date_default_year;
    class Date {
        Date(int month = DEFAULT_MONTH, int day = DEFAULT_DAY, int year = DEFAULT_YEAR);
    };
}

定義:

namespace ephaitch {
    const int Date_default_month = 1;
    const int Date_default_day = 1;
    const int Date_default_year = 2001; 

    enum MONTH_IDS { JANUARY = 1, FEBRUARY, MARCH, APRIL, 
                     MAY, JUNE, JULY, AUGUST, 
                     SEPTEMBER, OCTOBER, NOVEMBER, DECEMBER 
                   };

    const string MONTH_NAMES[NUM_MONTHS] = { 
         "January", "February", "March",
         "April", "May", "June", 
         "July", "August", "September", 
         "October", "November", "December" 
        };

    Date(int month, int day, int year)
    {
    }
}

DEFINE を使わないで、すべての名前空間を汚染し、デバッグをやりにくくします。 enum はより優れていますが、それは意図した使い方ではないため、混乱する可能性があります。

0
追加された