LINUX.ORG.RU

как сделать красиво?

 


0

0

Есть функция, создающая строчку меню, в которую передаются название пункта меню, указатель на массив возможных значений и их количество.

videosys::Menu menu(attribute, indentFirstLine); 
std::string param[] = {"Да", "Нет"};
menu.AddEnumSwitch("Некий пункт",param, 2);
Теперь проблема - т.к. мы передаем указатель, то мы должны в месте вызова функции делать массив динамическим, т.е. членом класса, чего сильно не хочется. Использовать контейнер можно, но выглядеть будет очень громоздко всего лишь для вызова одной функции (1 строка будет под его объявление, 2,...,n+1 будут заняты под push_back-и или insert-ы). К сожалению, компилятор старого стандарта не поддерживает инициализацию при объявлении того же вектора. Как лучше обойти данный момент?

PS: в какие теги погружать код на ЛОРе?



Последнее исправление: Burns (всего исправлений: 2)

std::string param[] = {«Да», «Нет»};

Вы уверены, что это лучше чем const char* param[] = {«Да», «Нет»};

menu.AddEnumSwitch(«Некий пункт»,param, 2);

Предыдущий язык был паскаль?

andreyu ★★★★★
()

красиво - это отдельные классы для Menu, MenuItem (и его производных), ItemFactory и так далее. Много текста, долго и нудно делать, зато «лучше день потерять, потом за час долететь».

ваш метод «menu.AddEnumSwitch(„Некий пункт“,param, 2);» видимо делает «menu.add(EnumSwitch(..))» - то есть смешивает реализацию разных сущностей в один класс, откуда потом вырастет гораздо большие проблемы чем «неудобно писать»

зы. А что заставляет делать собственные меню при очевидном наличии аналогов во фреймворке ?

MKuznetsov ★★★★★
()
Ответ на: комментарий от andreyu

Вы уверены, что это лучше чем const char* param[] = {«Да», «Нет»};

Да, уверен. Помести туда, например, строки длиной более килобайта и посмотри, что с ними будет. Раньше я все делал с помощью char *, но потом понял, что это небезопасно и неудобно в использовании.

Эмм почему паскаль? Что именно не нравится? Типичный гугловский код стандарт (пробел только забыл)

Burns
() автор топика
Ответ на: комментарий от puding
class Menu
{

public:
	Menu(MenuAttributes attributes, int y0newString);
	~Menu();

	void AddNumericSwitch(std::string title, int startValue, int minValue, int maxValue, int stepValue, int countSymbols = 0);
	void AddEnumSwitch(std::string title, std::string* values, int countValues);
	void Draw();
	
	void PushLeft();
	void PushRight();
	void PushUp();
	void PushDown();
	void PushEnter();

private:
	void createFont();
	MenuAttributes _mAttr;
	int _y0newString;
	int _countCursorPosition;
	int _cursor;
	Panel* _panel;
	std::vector<Widget *> _strings;
	

};
void videosys::Menu::AddEnumSwitch(std::string title, std::string* values, int countValues)
{
	_strings.push_back(new EnumSwitch(_mAttr, _mAttr.y0 + _y0newString, title, values, countValues));	
	_strings.at(_countCursorPosition)->SetActive(_cursor - 1 == _countCursorPosition);

	_y0newString += _strings.at(_countCursorPosition)->GetHeight() + _mAttr.step;
	++_countCursorPosition;

}
Burns
() автор топика
Ответ на: комментарий от MKuznetsov

Согласен. Так бы было правильнее, но пока не требуется и вообще вроде бы не пригодится.

В смысле смешивает разные сущности в один класс? Вы не про полиморфизм ли сейчас?

Ограничивает то, что работа идет на SDL, а open_gl вместе с ним не очень нужно пока изучать

Burns
() автор топика

пока переделываю все на вектор, а вообще жду ваших умных мыслей

Burns
() автор топика
Ответ на: комментарий от Burns

Да, уверен. Помести туда, например, строки длиной более килобайта и посмотри, что с ними будет.

Строка меню более килобайта длинной? У вас явно что то не так.
А что, кстати, будет то?

Раньше я все делал с помощью char *, но потом понял, что это небезопасно и неудобно в использовании.

Почему небезопасно и неудобно?

Эмм почему паскаль? Что именно не нравится? Типичный гугловский код стандарт (пробел только забыл)

В массиве у вас два элемента, а вы передаете индекс, выходящий за границу. Потому и подумал, что раньше писали на паскале, поскольку там индексация начинается с единицы.

andreyu ★★★★★
()
Ответ на: комментарий от Burns

void AddNumericSwitch(std::string title, int startValue, int minValue, int maxValue, int stepValue, int countSymbols = 0);
void AddEnumSwitch(std::string title, std::string* values, int countValues);

std::string title - вы уверены, что понимаете, что делаете?

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

В массиве у вас два элемента, а вы передаете индекс, выходящий за границу. Потому и подумал, что раньше писали на паскале, поскольку там индексация начинается с единицы.

Передаётся, наверное, не индекс а размер.

Внутри будет что-то типа

for(int i = 0; i < size;...

Опять же, это с стл вполне согласуется (передача «итератора» на элемент следующий за последним).

Кстати, в паскале при обьявлении массива указывается с какого индекса он начинается:

var
  i: Integer;
  b: array [50..100] of Integer;

А для динамических массивов индексация начинается как раз с нуля.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Передаётся, наверное, не индекс а размер.

Я в этом не уверен. Совсем не уверен:

std::string param[] = {"Да", "Нет"};
menu.AddEnumSwitch("Некий пункт",param, 2);

Зачем тут нужно передавать размер? Почему не индекс? Вообще этот и последующий код до ужаса стремный. Не удивительно, что у ТС проблемы.

andreyu ★★★★★
()
Ответ на: комментарий от DarkEld3r

Кстати, в паскале при обьявлении массива указывается с какого индекса он начинается:
А для динамических массивов индексация начинается как раз с нуля.

Возможно, паскаль не видел уже больше 20 лет.

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

Вообще этот и последующий код до ужаса стремный. Не удивительно, что у ТС проблемы.

С этим спорить не буду. (:

Я в этом не уверен. Совсем не уверен:

Можно поспорить:

void videosys::Menu::AddEnumSwitch(std::string title, std::string* values, int countValues)
{
	_strings.push_back(new EnumSwitch(_mAttr, _mAttr.y0 + _y0newString, title, values, countValues));	
Параметр всё-таки называется «countValues».

Правда что такое «EnumSwitch» мы не знаем.

DarkEld3r ★★★★★
()
Ответ на: комментарий от Burns

Передавай строки

const std::string& title

инчае у тебя лишние объекты конструируются. (мог ошибится, но суть в неизменяемой ссылке)

anonymous
()

Может, так:

void videosys::Menu::AddEnumSwitch(const char* title, const char** values, int countValues)
{

    //

}

/**************************************************/

const char* name = "Некий пункт";
const char* param[] = {"Yes", "No"};
int countValues = 2;
puding
()
Ответ на: комментарий от anonymous

инчае у тебя лишние объекты конструируются

Как недавно выяснилось, у g++ std::string сами по себе умные указатели, так что их можно смело передавать по значению и возвращать из функций.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Как недавно выяснилось, у g++ std::string сами по себе умные указатели, так что их можно смело передавать по значению и возвращать из функций.

Ты, наверное, про «rvalue references» из нового стандарта?

Вот только это не всегда работает и не всегда нужно.

DarkEld3r ★★★★★
()
Ответ на: комментарий от DarkEld3r

Ты, наверное, про «rvalue references» из нового стандарта?

нет, там счетчик ссылок внутри

wota ★★
()
Ответ на: комментарий от DarkEld3r

функция уоторой вы передаете массив сама должна копию делать в свой контейнер который разрушится когда умрет объект меню

anonymous
()
Ответ на: комментарий от anonymous

а вообще на дворе 21 век а вы еще без GC пишите неандертальцы

anonymous
()
Ответ на: комментарий от DarkEld3r

Вот только это не всегда работает и не всегда нужно.

Не работает в MS VC. Там, говорят, происходит копирование.

i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

Но всё равно же будет дёргатся конструктор для string разве нет?

При -O3 многое инлайнится же. Не факт, что там будет вызов функции.

А ещё можно спокойно возвращать из функций небольшого размера структуры, не заморачиваясь с ссылками и указателями.

i-rinat ★★★★★
()
Последнее исправление: i-rinat (всего исправлений: 1)
Ответ на: комментарий от anonymous

Правда, мне кажется, что всё же не стоит полагаться.

Недавно вместо хитрой арифметики отрезков я взял и тупо сделал цикл под всем элементам массива (около 30 тысяч). И знаешь что? Никакого значимого влияния на производительность. Всё время уходит на операции с диском. Сначала это была заглушка, я хотел её потом переписать «чтобы было красиво», но сейчас не вижу причины делать из короткого и простого кода сложный и запутанный ради каких-то сотых долей процента.

i-rinat ★★★★★
()
Ответ на: комментарий от nanoolinux

Нет, не передаю. Но вопрос актуальный, да и много где советуется передавать объекты по ссылке. Сейчас немного погуглил нашёл пару топиков:
http://stackoverflow.com/questions/1885785/passing-c-strings-by-value-or-by-r...
http://stackoverflow.com/questions/10231349/are-the-days-of-passing-const-std...
Но пока полностью не прочитал и отложил вопрос. Да и на С++ я не пишу.

anonymous
()
Ответ на: комментарий от nanoolinux

Вот нашёл:

Scott Meyers (in Effective C++) recommends that you use pass by const ref for all types, except for builtin types (char, int, double, etc.), for iterators and for function objects (classes deriving from std::*_function).
пруф искать лень, но вроде там же и прочёл.

anonymous
()
Ответ на: комментарий от DarkEld3r

Параметр всё-таки называется «countValues».

А, ну да. Только в топике этого объявления не было.

А std::string title и вовсе стремная штука.

andreyu ★★★★★
()
Ответ на: комментарий от i-rinat

Как недавно выяснилось, у g++ std::string сами по себе умные указатели, так что их можно смело передавать по значению и возвращать из функций.

Полагаться на это не стоит, лучше просто писать правильно.

andreyu ★★★★★
()
Ответ на: комментарий от anonymous

нафиг мне твой пруф? я и так знаю как оно работает и ещё раз тебе напоминаю, что преждевременная оптимизация - зло.

nanoolinux ★★★★
()
Ответ на: комментарий от andreyu

лучше просто писать правильно.

а как правильно?

string itos(int i)
{
  stringstream ss;
  ss << i;
  return ss.str();
}
int main(void)
{
  string s = itoa(10);
  cout << s << endl;
}

versus

void itos(int i, string &s)
{
  stringstream ss;
  ss << i;
  s = ss.str();
}
int main(void)
{
  string s;
  itoa(10, s);
  cout << s << endl;
}

itoa(10, s) менее очевидно, чем itoa(10), разве нет? Даже в таком примере видно, что код яснее и меньше напрягает мозг. У меня мозг ограничен и я хочу освободить там место для более важных, чем жонглирование параметрами, вещей. Поэтому для меня правильный вариант — первый.

i-rinat ★★★★★
()
Ответ на: комментарий от nanoolinux

преждевременная оптимизация - зло

Да никто не спорит. Как и песимизация. А пруф касаемо, утверждения, что Скотт Майерс рекомендует всё передавать по (не)константной ссылке кроме простых типов. И ему я пока больше верю.

anonymous
()
Ответ на: комментарий от i-rinat

И второй вариант в общем случае будет быстрее, хотя он говно.

andreyu ★★★★★
()
Ответ на: комментарий от andreyu

Хотя бы из-за stringstream.

За деревьями леса не увидел. Посредственный написанный код лучше идеального ненаписанного.

И второй вариант в общем случае будет быстрее

О, да. Тысячные доли секунды меня очень волнуют.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

тысячные доли секунды? не многовато ли? на копирующий конструктор std::string от силы пару наносекунд будет. да и ещё и не факт что он будет вызван.

nanoolinux ★★★★
()
Ответ на: комментарий от nanoolinux

Он на stringstream ругался. Ну а я взял оценку верхней границы.

i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

ты бы не верил, а подумал своей головой почему так.

const string & даёт возможность не вызывать копирующий конструктор. в этом вся фишка. да вот беда, const запретит менять строку, а следовательно cow не будет. а передача string по значению будет тем же, что и передать long long например. так что разницы нет, писать только больше.

nanoolinux ★★★★
()
Ответ на: комментарий от i-rinat

За деревьями леса не увидел. Посредственный написанный код лучше идеального ненаписанного.

О каком коде вы речь ведете? То, что в топике показано - говно. Можно и дальше успокаивать себя тем, что пусть хоть говно, но написанное.

andreyu ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.