Страшный зверь сиплюсплюс

Закрытые или заброшенные проекты, не состоявшие в Клубе, но имевшие ветку на форуме.

Модератор: Jolly Roger

Есть ли смысл в переходе на С++?

Нет, переписывай заново на fpc
7
25%
Да, причем пиши под *никсы
9
32%
Нет, переходи на VBS
0
Голосов нет
А почему не Ява?
12
43%
 
Всего голосов: 28

Аватара пользователя
Харука-тян
Мастер
Сообщения: 544
Зарегистрирован: 29 ноя 2006, 00:23
Контактная информация:

Страшный зверь сиплюсплюс

Сообщение Харука-тян » 07 фев 2010, 23:37

Начала постепенно портировать своё творение на С++. Теперь буду хныкать каждый раз, когда получу граблями по лбу. Среда разработки - MinGW Studio. Живёт на SourceForge.

Код: Выделить всё

svn co https://lanceranr.svn.sourceforge.net/svnroot/lanceranr lanceranr
1) если компилятор пишет, что класс имеет виртуальные методы, это правда или ему мерещится? (все виртуальные методы предка были перекрыты потомком)
2) позволяет ли C++ делать закольцованные обращения заголовков? У меня то, что сейчас есть, не компилируется ни под каким предлогом, и причина кажется где-то здесь. (node.h, uid.h)
"Женщина верит, что дважды два будет пять, если хорошенько поплакать и устроить скандал" (© Дж. Элиот).
ИзображениеИзображение

Аватара пользователя
Cfyz
Сообщения: 764
Зарегистрирован: 30 ноя 2006, 10:03
Откуда: Санкт-Петербург
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Cfyz » 08 фев 2010, 01:34

1) Три метода в TEObject объявлены как виртуальные, но не имеют тела и не помечены явно как тела не имеющие ("чисто виртуальные"). Добавь пустое тело функциям, проблема должна исчезнуть. Хотя как исчезнуть, реализации этих функций в TEClass приведут к stack overflow, т.к. у компилятора нет никакого резона выбирать глобальную функцию из debug.h вместо лежащей рядом (в том же классе) функции с такой же сигнатурой.

2) Проблема не в закольцованности, #ifndef / #define у тебя, по идее, это устраняет. Другое дело -- TUIDStore* UIDs; в uid.h. Так как этот файл включается по крайней мере в node.cpp и uid.cpp, два соответствующих объектных модуля получают одинаковые и дублирующие друг друга при компоновке переменные. Выход -- разместить честное объявление переменной в одном .cpp, а во все другие (или в подключаемый хидер) прописать extern TUIDStore* UIDs; то бишь "да-да, эта переменная внешняя и еще где-то есть".

Вообще, о каких закольцованных обращениях заголовков может идти речь, если #include -- это никакая не инструкция языка программирования, а самое простое включение указанного файла целиком в то самое место, где стоит #include. Я где-то даже забавную хитрость видел в плане инициализации огромных статических массивов:

Код: Выделить всё

double some_array[2048] = 
{
    #include "some_array_values.csv"
};
И, соответственно, файл some_array_values.csv:

Код: Выделить всё

0.25, 0.27, 0.45, 0.67, // ... и так далее 2 тысячи элементов, сгенеренных чем-либо
edit: Все эти квадратные колеса с Prev/Next, Add/Attach/Detach в TNode -- идея не очень здравая. Глянь стандартную библиотеку шаблонов и не трать свое время на велосипеды, как бы у тебя ни лежала к ним душа.


P.S. От глосования воздержался, т.к. ни один из ответов не подходит. Как chaotic neutral персонаж, я, разумеется, за С++. Но это на (не)определенное время существенно замедлит продвижение проекта, стоит ли?
Cfyz теперь - наглая морда.

Аватара пользователя
Харука-тян
Мастер
Сообщения: 544
Зарегистрирован: 29 ноя 2006, 00:23
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Харука-тян » 08 фев 2010, 01:40

extern помог, спасибо. Объяснение того, что значит #include тоже пригодится. А с виртуальными методами ничего не вышло.
"Женщина верит, что дважды два будет пять, если хорошенько поплакать и устроить скандал" (© Дж. Элиот).
ИзображениеИзображение

Аватара пользователя
Jesus05
Сообщения: 1824
Зарегистрирован: 02 дек 2009, 07:50
Откуда: Норильск, сейчас Санкт-петербург.
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Jesus05 » 08 фев 2010, 02:33

ответил "А почему не Ява?" :) но просто потому что считаю:
1. Зачем переписывать код если он работает там где ты его писала?
2. Зачем переписывать код если он даже там где ты его писала не работает?

Переписывать код конечно полезно но тогда когда ты уже понимаешь а что-же было не так в прошлой версии кода.

(это только мое личное мнение :) не более, а с явой знаком поверхностно т.ч. этот ответ не вопринимать как совет к действию)

Аватара пользователя
Jesus05
Сообщения: 1824
Зарегистрирован: 02 дек 2009, 07:50
Откуда: Норильск, сейчас Санкт-петербург.
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Jesus05 » 08 фев 2010, 03:22

Харука-тян писал(а):extern помог, спасибо. Объяснение того, что значит #include тоже пригодится. А с виртуальными методами ничего не вышло.
А что не выходит с виртуальными кассами?

(далее мои коментарии не принимай близко к сердцу :) )

Код: Выделить всё

if (LogStart())return(1);
эта строчка в переводи на русский звучит так:

Код: Выделить всё

Если LogStart вернул "true", то выйти из функции вернув 1
что-то мне подсказывает что ты хотела написать немного по другому.

Код: Выделить всё

if (!LogStart())return(1);

Код: Выделить всё

Если LogStart вернул "false", то выйти из функции вернув 1
едит:
а вообще у меня к этой функции перетензия есть еще :) я забыл пока писал остальное.

Код: Выделить всё

bool LogStart()
{
	LogFile = fopen("log.txt", "w");
	if (!LogFile) return(0);
	
	return(LogFile);
};
по сути if (!LogFile) return(0); звучит примерно так "Если указатель на LogFile равен нулю то вернуть ноль".
но если посмотреть на функцию повнимательнее то видно что даже если LogFile не равен нулю мы все равно возвращает что что в LogFile (return (LogFile)) так может проще для чтения будет

Код: Выделить всё

bool LogStart()
{
	LogFile = fopen("log.txt", "w");
	return(LogFile);
};
Если ноль так все равно ноль, если не ноль все равно не ноль.
а вообще как по мне то правельнее так :) но это только мое мнение пиши как считаешь нужным никого не слушай :) (ну слушай только то что помогает сделать твой код рабочим, а то что я сейчас пишу делает твой код "красивым на мой взгляд")

Код: Выделить всё

bool LogStart()
{
	LogFile = fopen("log.txt", "w");
	if (!LogFile) return false;
	
	return true;
};
ну с Экстерном могу тебе посоветовать делать как я :) я в каждом проекте создаю 2 файла Extern.h и Define.h и в каждый хеадер инклудю Extern.h. файл такого вида обычно.

Код: Выделить всё

#ifndef ExternH
#define ExternH

#include "Define.h"
#include <windows.h>
extern HDC  hDC;                
extern HWND  hWnd;              
extern HINSTANCE  hInstance;    
extern HGLRC  hRC;              
extern ULONG QuitValue;           
extern bool Working;              
extern bool Active;

#endif

здесь переписаны глобальные переменные которые должны быть видны во всем проекте а создаются эти переменные уже в каком-нить из .cpp

далее :) продолжим разюирать твой код.

Код: Выделить всё

void Log(char* LogString)
{
	fwrite(LogString, sizeof(*LogString), 80, LogFile);
	fwrite("\n",1,1,LogFile);
};
fwrite пишет "sizeof(*LogString) * 80" байт, но строка может же быть и меньше, а что если мы залезем в "чужую" память? может все-же подгрузить string.h и написать.

Код: Выделить всё

void Log(char* LogString)
{
	fwrite(LogString, sizeof(*LogString), strlen(LogString), LogFile);
	fwrite("\n",1,1,LogFile);
};
а то такой код

Код: Выделить всё

int main(int, char* [])
{
	if (!LogStart())return(1);

  TEObject *a = new (TEClass);

  a->Log("test"); 

  delete a;
  
	LogDone();
	return 0;
}
привел к тому что в файл попало что-то типа "test cxvl dskfxo dskfjhv dxkvc"
далее :)

Код: Выделить всё

void TEClass::Log(char* LogString)
{
	Log(LogString);
};
когда ты внутри класса вызываешь функцию одноименную с функцией класса компилятор вызовет функцию класса т.е. в данном коде функция вызывает сама себя :) потом снова сама себя... = бесконечное вложение.
Что-бы вызвать функцию вне класса пиши

Код: Выделить всё

void TEClass::Log(char* LogString)
{
	::Log(LogString);
};
а лучше конечно не допускать одинаковых имен, запутаешься... но с другой стороны, т.к. эти функции у тебя "базовые" почему бы их не засунуть в базовый класс TEObject как виртуальные и если нужно будет переделывать их в дочерних классах.

ну вроде все что бросилось в глаза :) если есть еще вопросы пиши будем форумом обсуждать и подсказывать.

Аватара пользователя
Maelstrom
Мастер
Сообщения: 2062
Зарегистрирован: 26 ноя 2006, 14:19
Откуда: г. Усть-Кирдык
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Maelstrom » 08 фев 2010, 08:25

Хватит мелочиться, изучай ромхакинг и пиши игру сразу на супернинтендо
Айв кнгенгах Йог-Сотот

Аватара пользователя
Aerton
Сообщения: 503
Зарегистрирован: 11 авг 2007, 02:58
Откуда: Новосибирск
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Aerton » 08 фев 2010, 08:43

Не хватает random.h
Харука-тян писал(а):1) если компилятор пишет, что класс имеет виртуальные методы, это правда или ему мерещится? (все виртуальные методы предка были перекрыты потомком)
Если он настаивает, значит так оно и есть. Из-за рандома компиляция срубилась, не дойдя до этой ошибки. Может быть, не хватает деструктора, который тоже должен быть виртуальным?

Аватара пользователя
Cfyz
Сообщения: 764
Зарегистрирован: 30 ноя 2006, 10:03
Откуда: Санкт-Петербург
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Cfyz » 08 фев 2010, 09:01

Харука-тян писал(а):А с виртуальными методами ничего не вышло.
Aerton писал(а):Может быть, не хватает деструктора, который тоже должен быть виртуальным?
Презанятно, сегодняшне-ночной trunk с моими правками нормально собирается Eclipse/GCC под моей fedora; trunk же текущий, если выбросить random.cpp, не вызывает возмущения у MSVC 2008 на работе.

Деструктор в этом классе, действительно, должен быть виртуальным (но из соображений полиморфизма, а не синтаксиса).

Алсо, если проглядеть предупреждения MSVC:

Код: Выделить всё

TUIDStore::~TUIDStore()
{
	delete[] Data;
};
Что это? Удаление статически размеченной переменной оператором delete? NO WAI. Если удалить все же хочется (что совершенно не нужно, раз срок жизни массива равен сроку жизни объекта), Data дожн быть объявлена как указатель (указателей, TNode** Data;) и выделен в конструкторе: Data = new TNode[0xFFFF]; Но лесом все это, шестьдесят тысяч пяьсот тридцать пять О_о указателей сплошным массивом (256кб, между делом) -- это не Ъ. Я бы, наверное, использовал ассоциативный список-словарь, тот же std::map. Другое дело, стараюсь избегать необходимости вести такие списки в принципе.

GetFreeID() того же класса вообще скопище неясного. К примеру, необязательно возвращает значение. В случае, если все ID используются, do-while выполнится ровно один раз и выйдет без единого return. Каким образом у MSVC это не ошибка, а предупреждение -- выше моего разумения. Выход за границу Data также возможен, проверка IDCount на равенство 0xFFFF выполняется не всегда.
Cfyz теперь - наглая морда.

Аватара пользователя
Aerton
Сообщения: 503
Зарегистрирован: 11 авг 2007, 02:58
Откуда: Новосибирск
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Aerton » 08 фев 2010, 09:25

Действительно, без random.cpp всё собирается.
Кажется, я понял, что с virtual: у тебя какая версия gcc? Если достаточно старая, то он ещё не умел делать inline virutal. Либо обнови компилятор, либо тела всех виртуальных функций должны быть в .cpp

Код: Выделить всё

TUID TUIDStore::GetFreeID()
{
        do
        {
                ...
        }
        while (++OverFlow = 0xFFFF);
};
Это не сравнение, а присвоение.

Аватара пользователя
Максим Кич
Администратор
Сообщения: 1593
Зарегистрирован: 03 дек 2006, 20:17
Откуда: Витебск, Беларусь
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Максим Кич » 08 фев 2010, 11:55

Золотое правило: работает — не ломай! Лично я вижу для разработчика рогалика только один повод перехода на C++: libtcod.
Aerton писал(а):Это не сравнение, а присвоение.
Классическая проблема паскалянтов в языках с сишным синтаксисом. Есть вторая ещё, про неё анекдот хороший:
Приходит паскалянт к доктору.

— Доктор, я с паскаля на С перехожу. Избавьте меня от зависимости!
— От какой зависимости?
— От регистровой!
Dump the screen? [y/n]

Аватара пользователя
Aerton
Сообщения: 503
Зарегистрирован: 11 авг 2007, 02:58
Откуда: Новосибирск
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Aerton » 08 фев 2010, 12:38

Максим Кич писал(а):Золотое правило: работает — не ломай!
Это верно. Но видимо что-то не работало, раз пришлось начать заново.
Максим Кич писал(а):Лично я вижу для разработчика рогалика только один повод перехода на C++: libtcod.
Вообще-то он написан на каком-то диалекте С. Для С++ всего лишь обёртка, для fpc можно было бы использовать точно такую же. Это опять же, если tcod вообще рассматривать с положительной стороны, так что и этот довод не в счёт :)
Максим Кич писал(а):Классическая проблема паскалянтов в языках с сишным синтаксисом. Есть вторая ещё
Скорее проблема выключенных сообщений компилятора или их игнорирования. А разный регистр вроде и в паскале избегается, как плохой стиль.

Аватара пользователя
MyParanoya
Сообщения: 159
Зарегистрирован: 01 дек 2009, 19:13

Re: Страшный зверь сиплюсплюс

Сообщение MyParanoya » 08 фев 2010, 13:46

в С она тоже есть (2Кич)
я за. ну тут nobody cares.

Аватара пользователя
Xecutor
Мастер
Сообщения: 734
Зарегистрирован: 25 мар 2008, 08:32

Re: Страшный зверь сиплюсплюс

Сообщение Xecutor » 08 фев 2010, 14:32

ИМХО при разработке рогалика гораздо больше архитектурных проблем,
чем проблем, которые разрешаются выбором "правильного" языка.
Теоретически языки с GC решают проблему памяти.
Но ИМХО это меньшая из потенциальных проблем.

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

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

Аватара пользователя
Максим Кич
Администратор
Сообщения: 1593
Зарегистрирован: 03 дек 2006, 20:17
Откуда: Витебск, Беларусь
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Максим Кич » 08 фев 2010, 23:14

MyParanoya писал(а):в С она тоже есть (2Кич)
Ну да. Как несложно догадаться в С тоже сишный синтаксис :)
Xecutor писал(а):ИМХО при разработке рогалика гораздо больше архитектурных проблем,
чем проблем, которые разрешаются выбором "правильного" языка.
Золотые слова! Ну и я добавлю проблемы алгоритмизации, которые тоже, по большому счёту, от языка зависят мало.
Dump the screen? [y/n]

Аватара пользователя
Харука-тян
Мастер
Сообщения: 544
Зарегистрирован: 29 ноя 2006, 00:23
Контактная информация:

Re: Страшный зверь сиплюсплюс

Сообщение Харука-тян » 09 фев 2010, 16:17

Aerton писал(а):разный регистр вроде и в паскале избегается, как плохой стиль
По-крайней мере, мной точно.

Господа, а форсинг Явы - это юмор такой, или к этому есть обоснуй?
"Женщина верит, что дважды два будет пять, если хорошенько поплакать и устроить скандал" (© Дж. Элиот).
ИзображениеИзображение

Ответить

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и 1 гость