简体   繁体   English

我应该在哪里放置班级需要的常量,以保持全局空间的自由?

[英]Where do I place constants needed by my class in order to keep global space free?

First: I know how to write the program, so I'm not asking for help with that. 第一:我知道如何编写程序,因此我不寻求帮助。 However, I am pasting a copy of the problem so you can see what the assignment entails. 但是,我正在粘贴问题的副本,以便您可以看到分配的含义。 My question is specifically aimed at where do you place variables to keep from making everything global? 我的问题专门针对您在哪里放置变量以防止使所有内容全局化?

Assignment 分配

Design a class called Date that has integer data members to store month, day, and year. 设计一个名为Date的类,该类具有整数数据成员以存储月,日和年。 The class should have a three-parameter default constructor that allows the date to be set at the time a new Date object is created. 该类应具有一个三参数的默认构造函数,该构造函数允许在创建新的Date对象时设置日期。 If the user creates a Date object without passing any arguments, or if any of the values passed are invalid, the default values of 1, 1, 2001 (ie, January 1, 2001) should be used. 如果用户创建的Date对象没有传递任何参数,或者传递的任何值无效,则应使用默认值1、1、2001(即2001年1月1日)。 The class should have member functions to print the date in the following formats: 该类应具有成员函数以下列格式打印日期:

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

Questions 问题

1) The teacher has instructed us to avoid using magic numbers in our code, so the first question is regarding my implementation of the default constructor: 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);

Is this correct? 它是否正确?

2) The class needs access to an array of string objects which hold the month names so I can use them for date outputs which display the month name instead of the month number. 2)该类需要访问包含月份名称的string对象数组,因此我可以将它们用于显示月份名称而不是月份编号的日期输出。 I used an enum for the numeric month (which will be used for the switch ). 我为数字月份使用了一个enum (将用于switch )。

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" };

The question for this part, is where do you place them? 这部分的问题是,您将它们放在哪里?

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. 我们也没有遍历指针,但是我们可以使用引用。

Thanks for your help! 谢谢你的帮助!

I would ask the instructor but he is out of town and the assignment is due tomorrow. 我想请教官,但他不在城里,所以作业明天就要交。

1) Defines are ugly. 1)定义是丑陋的。 static const int members are what I would do, but you can't ... How about enums? 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) A static member array is just what you need. 2)静态成员数组正是您所需要的。 But since you can't ... maybe static local variables: 但是由于您不能...也许是静态局部变量:

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]);
    }
};

If you would like to define a constant without polluting a global namespace, two of your best options are using namespaced globals or class statics. 如果您想定义一个常量而不污染全局名称空间,那么您最好的两个选择是使用名称空间的全局变量或类静态变量。 Since you say you can't use class statics, I'll show an example of namespaced globals: 既然您说不能使用类静态变量,我将展示一个命名空间全局变量的示例:

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

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

You can access this variable as mynamespace::foo , or by using namespace mynamespace; 您可以使用mynamespace::foousing namespace mynamespace;来访问此变量using namespace mynamespace; (which is to be avoided in header files), or as just foo in any other function in the mynamespace namespace. (应避免在头文件中),或者在mynamespace命名空间中的任何其他函数中仅作为foo Since it's only accessible by something requesting (or otherwise being aware of) the mynamespace namespace, it avoids polluting the global namespace (and all the unfortunate name collisions this involves). 由于只能由请求(或以其他方式知道) mynamespace名称空间的人访问它,因此避免了污染全局名称空间(以及所有涉及此的不幸的名称冲突)。

For numeric values, an enum is another choice: 对于数值, enum是另一种选择:

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

These values are compile-time constants; 这些值是编译时常量。 you cannot take the address of them (but they can be a bit faster than const variables). 您不能使用它们的地址(但是它们可以比const变量快一点)。 Note that this can only be used for integer values. 请注意,这只能用于整数值。

Function statics are another good option: 函数静态是另一个不错的选择:

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

However, because the array is embedded deep into your implementation, it's not much better than a 'magic number'. 但是,由于数组已深深地嵌入到您的实现中,因此它并不比“幻数”好多少。

In your case, I do think either using enum s or (for non-integers) class statics would be best. 在您的情况下,我确实认为最好使用enum或(对于非整数)类静态变量是最好的。 If your professor has arbitrarily restricted use of class statics, put the variables at global scope (possibly in a namespace) and add a comment stating that you would have made them class statics if you were allowed to. 如果您的教授任意限制使用类静态变量,请将变量放在全局范围内(可能在名称空间中),并添加一条注释,说明如果允许的话,您将使它们成为类静态变量。

If you can't do static const members (or locals) you can just put everything in a namespace: 如果您不能执行static const成员(或本地成员),则可以将所有内容放入命名空间中:

declaration: 宣言:

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);
    };
}

definition: 定义:

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)
    {
    }
}

Don't use DEFINE s, they pollute all namespaces, and make debugging trickier. 不要使用DEFINE ,它们会污染所有名称空间,并使调试更加棘手。 enum s are better, but since that's not the intended usage, it can be confusing. enum是更好的方法,但是由于这不是预期的用法,因此可能会造成混淆。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM