Во-первых: я знаю, как писать программу, поэтому я не прошу о помощи в этом. Тем не менее, я вставляю копию проблемы, чтобы вы могли видеть, что подразумевает назначение. Мой вопрос конкретно направлен на то, где вы помещаете переменные, чтобы не делать все глобальным?
<Сильный> Назначение
Создайте класс под названием Date, в котором есть целые члены данных для хранения месяца, дня и года. Класс должен иметь трехпараметрический конструктор по умолчанию, который позволяет установить дату в момент создания нового объекта Date. Если пользователь создает объект Date без передачи каких-либо аргументов или если какое-либо из переданных значений недопустимо, следует использовать значения по умолчанию 1, 1, 2001 (т.е. 1 января 2001 года). Класс должен иметь функции-члены для печати даты в следующих форматах:
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
, которые содержат имена месяцев, поэтому я могу использовать их для выходов даты, которые отображают имя месяца вместо номера месяца. Я использовал 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" };
Вопрос в этой части, где вы их размещаете?
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.
Спасибо за вашу помощь!
Я бы спросил у инструктора, но он уехал из города, и назначение назначено завтра.
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]);
}
};
Если вы хотите определить константу без загрязнения глобального пространства имен, два из ваших лучших вариантов будут использовать глобальные пространства имен или статику классов. Поскольку вы говорите, что не можете использовать статику класса, я покажу пример глобалов с именами:
// .h file
namespace mynamespace {
extern const int foo;
};
// later, in a .cpp file
namespace mynamespace {
const int foo = 42;
};
Вы можете получить доступ к этой переменной как mynamespace :: foo
или через с помощью пространства имен mynamespace;
(чего следует избегать в заголовочных файлах) или как только foo
в любой другой функции в пространстве имен mynamespace
. Поскольку он доступен только для чего-то, запрашивающего (или иным образом осознающего) пространство имен mynamespace
, он позволяет избежать загрязнения глобального пространства имен (и все связанные с этим неудачные столкновения имен).
Для числовых значений используется следующий код enum
:
class foo {
enum { CONST_FOO = 42, CONST_BAR = 24 };
};
Эти значения являются константами времени компиляции; вы не можете взять их адрес (но они могут быть немного быстрее, чем переменные const
). Обратите внимание, что это может использоваться только для целочисленных значений.
Функция статики - еще один хороший вариант:
void myclass::somefunction() {
static const char *monthNames[] = { "JANUARY", ... };
//...
}
Однако, поскольку массив встроен глубоко в вашу реализацию, он не намного лучше, чем «магическое число».
В вашем случае я считаю, что лучше всего использовать класс enum
s или (для нецелых) классов. Если ваш профессор произвольно ограничил использование статики класса, поместите переменные в глобальную область действия (возможно, в пространство имен) и добавьте комментарий, в котором говорится, что вы сделали бы их классической статикой, если вам было разрешено.
Если вы не можете сделать 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
s, они загрязняют пространства имен all и затрудняют отладку. enum
s лучше, но поскольку это не намеренное использование, это может ввести в заблуждение.