Продолжаю штудировать самоучитель Шилтда и обратил внимание что в одном из своих примеров он объевляет enum список для членов класса, которые во многих других языках программирования были бы просто булево свойствами:
// Fruit.h
#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstring>
using namespace std;
enum yn {no, yes};
enum color {red, yellow, green, orange};
class Fruit {
public:
enum yn annual;
enum yn perennial;
enum yn tree;
enum yn tropical;
enum color color;
char name[40];
};
class Apple : public Fruit{
enum yn cooking;
enum yn crunchy;
enum yn eating;
public:
void seta(char*, enum color, enum yn, enum yn, enum yn);
void show();
};
class Orange : public Fruit {
enum yn juice;
enum yn sour;
enum yn eating;
public:
void seto(char*, enum color, enum yn, enum yn, enum yn);
void show();
};
// Fruit.cpp
#include "Fruit.h"
char* c[] =
{
"red", "yellow", "green", "orange"
};
void out(enum yn);
void Apple::seta(char *name, enum color color, enum yn cooking,
enum yn crunchy, enum yn eating)
{
strcpy(this->name, name);
annual = no;
perennial = yes;
tree = yes;
tropical = no;
this->color = color;
this->cooking = cooking;
this->crunchy = crunchy;
this->eating = eating;
}
void Orange::seto(char *name, enum color color, enum yn juice,
enum yn sour, enum yn eating)
{
strcpy(this->name, name);
annual = no;
perennial = yes;
tree = yes;
tropical = yes;
this->color = color;
this->juice = juice;
this->sour = sour;
this->eating = eating;
}
void Apple::show()
{
cout << name << " яблоко — это: " << "\n";
cout << "Однолетнее растение: "; out(annual);
cout << "Многолетнее растение: "; out(perennial);
cout << "Дерево: "; out(tree);
cout << "Тропическое: "; out(tropical);
cout << "Цвет: " << c[color] << "\n";
cout << "Легко приготавливается: "; out(cooking);
cout << "Хрустит на зубах: "; out(crunchy);
cout << "Съедобное: "; out(eating);
cout << endl;
}
void Orange::show()
{
cout << name << " яблоко — это: " << "\n";
cout << "Однолетнее растение: "; out(annual);
cout << "Многолетнее растение: "; out(perennial);
cout << "Дерево: "; out(tree);
cout << "Тропическое: "; out(tropical);
cout << "Цвет: " << c[color] << "\n";
cout << "Годится для приготовления сока: "; out(juice);
cout << "Кислый: "; out(sour);
cout << "Съедобное: "; out(eating);
cout << endl;
}
void out( enum yn x)
{
if (x == no) cout << "нет" << endl;
else cout << "да" << endl;
};
Я предположил что возможно таким образом автор избегает создание новых сущностей и экономит память, ссылаясь на уже созданный список вместо объявления временных булево констант. Прав ли я в своих догадках? Насколько корректно создавать такие списки для булево членов класса и стоит ли перенимать данную практику в реальных проектах.
Дополнительные вопросы, если позволите 2.1 Стоит ли в данном случае делать метод out inline методом? 2.2 Стоит ли прислушиваться к предупреждениям компилятора и избегать использования strcpy, заменив его yf strcpy_с? От каких опасностей он пытается меня предостеречь?
Никакого отношения к экономии памяти это не имеет.
Такая (или похожая) практика может быть полезной, когда в программе присутствуют функции с большим числом булевских по своей сути параметров, которые идут вереницей. Код, в котором в функцию передается цепочка булевских констант
foo(..., true, false, false, false, true, ...);
трудночитаем, ибо назначение каждого параметра в точке вызова ясно не сразу. Если же придать таким параметрам свои отдельные enum типы с именованными членами (даже если эти параметры по сути - просто "булевские"), то вызов функции будет читаться легче
foo(..., ENABLE_IO, NO_LOG, NO_ABORT, DISABLE_CACHE, YES_SORT, ...);
или с использованием scoped enums
foo(..., IO::ENABLE, LOG::NO, ABORT::NO, CACHE::DISABLE, SORT::YES, ...);
Также контроль типов при использовании этого приема защищает вас от указания аргументов в неправильном порядке (т.е. например от случайного "сдвига" цепочки аргументов влево или вправо).
В вашем примере, однако, делается не это. Поэтому особого смысла в том, что происходит в приведенном вами коде, не видно. Зачем могло понадобиться заменять огульный булевский тип на не менее огульный самодельный "булевский" тип - не ясно.
P.S. const
- нужен
const char* c[] =
{
"red", "yellow", "green", "orange"
};
Как, впрочем, и в множестве других мест.
возможно таким образом автор избегает создание новых сущностей и экономит память
Никакой экономии памяти тут нет. Есть только наглядность. Делайте так, как вам удобней (например, enum будет полезен, если потом захочется его расширить до { no, yes, maybe, ... }
)
Стоит ли в данном случае делать метод out inline методом?
Почему бы и нет? В любом случае спецификатор inline
- не строгое указание компилятору, он может поступить по-своему. А вот расположение кода внутри определения класса может быть просто наглядней, особенно если там одна-две строчки.
От каких опасностей он пытается меня предостеречь?
От случайного переполнения строки назначения.
В некоторых ситуациях enum
может оказаться лучше bool
: если вам вдруг захотелось добавить к набору значений maybe
, unknown
или что-либо в этом духе. Не думаю, что тут экономится память.
Оборудование для ресторана: новинки профессиональной кухонной техники
Частный дом престарелых в Киеве: комфорт, забота и профессиональный уход
Мне необходимо сделать фильтрацию по авторам статей на новостном порталеДолжен быть один пункт с undefined фильтром для отображения статей,...
Нужно сделать объект, который будет наследовать имя из своего прототипаНадо пропустить первый параметр, но не знаю как
Сначала делаю фокус в input и если следующий клик это label для этого инпута, то вылетает ошибка в консоль:
Доброго времени суток, господа! Нужно передать в php параметр - текущую ссылку(изначально загруженную), используя windowlocation