forum.boolean.name

forum.boolean.name (http://forum.boolean.name/index.php)
-   C++ (http://forum.boolean.name/forumdisplay.php?f=22)
-   -   Хитрая хитрость (http://forum.boolean.name/showthread.php?t=8571)

Mr_F_ 27.06.2009 23:00

Хитрая хитрость
 
итак, задача:

есть несколько классов.

допустим,

class human
{
int x,y,z, height, width;
};


class car
{
int x,y,z,speed;
};


нам нужно задавать внутренние значения для разных объектов разных классов, но имея лишь условный номер значения в объекте класса и
само значение. для примера я сделал что все значения всех классов - int.

т.е. пример условия: 2, 40
где 2 - номер значения (Y для обоих классов), а 40 - само значение, т.е. будь объект хоть car хоть human, в нём Y выставится в 40.

я предположил что надо сделать

массив, имеющийся в объекте каждого класса
который содержит указатели
на все значения (блин ну field'ы короче если говорить по блицевски)
мы сами суём в него указатели на филды при создании объекта в конструкторе класса.

в общем,
не мог бы кто реализовать такой пример, чтоб в результате это можно было уместить в одну функцию типа SetValue(num,value) для этих двух классов которые я привёл?

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

jimon 27.06.2009 23:23

Ответ: Хитрая хитрость
 
эх

Код:

class position
{
public:
int x,y,z;
};

class human:public position
{
public:
int height, width;
};

class car:public position
{
public:
int speed;
};

void setposition(position * obj)
{
obj->x = 1;
}

...
human * lol1 = new human;
setposition(lol1);
delete lol1;
car * lol2 = new car;
setposition(lol2);
delete lol2;
...

если ты хочешь назначать переменную по номеру то это можно, но является жудким говнокодом

ps. я делал бы так
Код:

class CVector3d
{
...
};

class CNode
{
protected:
CVector3d Position;
CVector3d Rotation;
CVector3d Scale;
...
public:
...
};

class CCar:public CNode
{
...
};

class CHuman:public CHuman
{
...
};


Genius 27.06.2009 23:34

Ответ: Хитрая хитрость
 
Цитата:

Сообщение от jimon (Сообщение 109271)
эх

Код:

class position
{
public:
int x,y,z;
};

class human:public position
{
public:
int height, width;
};


class car:public position
{
public:
int speed;
};

void setposition(position * obj)
{
obj->x = 1;
}

...
human * lol1 = new human;
setposition(lol1);
delete lol1;
car * lol2 = new car;
setposition(lol2);
delete lol2;
...

если ты хочешь назначать переменную по номеру то это можно, но является жудким говнокодом

Я бы вообще сделал так:

Код:

class Car;
class Human;

class GameObject
{
public:
    float x,y,z,pitch,yaw,roll;
    bool alive;

    bool isAlive() { return alive; }

    Car* getCar(){return 0;}
    Human* getHuman(){return 0;}

    virtual void setPosition(float _x,float _y,float _z){ x=_x;y=_y;z=_z; }
    virtual void setOrientation(float _pitch,float _yaw,float _roll){ pitch=_pitch;yaw=_yaw;roll=_roll;}

    virtual void update(){}
};

class Car : public GameObject
{
public:

    Car* getCar(){return this;}
 
    void setPosition(float x,float y,float z)
    {
          GameObject::setPosition(x,y,z);
          ....
    }

    void setOrientation(float pitch,float yaw,float roll)
    {
        GameObject::setOrientation(pitch,yaw,roll);
        ...
    }

    void update()
    {
        car physic update...
    }
};

class Human : public GameObject
{
public:

    Human* getHuman(){return this;}
 
    void setPosition(float x,float y,float z)
    {
          GameObject::setPosition(x,y,z);
          ....
    }

    void setOrientation(float pitch,float yaw,float roll)
    {
        GameObject::setOrientation(pitch,yaw,roll);
        ...
    }

    void update()
    {
        if(health <= 0)alive=false;
    }
};

class CarDriver : public Human
{
....
};

GameObject* car = new Car();
GameObject* human = new Humman();

if(car->getCar() != 0)car->setPosition(40,10,0);
if(human->getHuman() != 0)human->setPosition(40,15,0);

А вообще я не совсем понял вопрос.

jimon 27.06.2009 23:38

Ответ: Хитрая хитрость
 
Genius
Цитата:

Car* getCar(){return 0;}
Human* getHuman(){return 0;}
самый большой говнокод в ООП ! это хуже чем тупо модифицировать класс через смещение в указателях
я за такое тебя бы уволил бы без разбирательств ;)

Genius 27.06.2009 23:43

Ответ: Хитрая хитрость
 
Цитата:

Сообщение от jimon (Сообщение 109273)
Genius

самый большой говнокод в ООП ! это хуже чем тупо модифицировать класс через смещение в указателях
я за такое тебя бы уволил бы без разбирательств ;)

Не бузи мне тут как бабка на базаре,ты делаеш так как тебе удобнее а я предпочитаю делать так как мне удобнее,и мне будет удобнее при переборе 100 объектов функции getCar узнать какие из них есть Car...

З.Ы. Я не говорю что твой код дерьмо,я вырозил своё мнение.

Mr_F_ 27.06.2009 23:52

Ответ: Хитрая хитрость
 
Цитата:

эх
не, xyz у меня тут случайно совпали, в реале могут быть абсолютно разные штуки там)

говнокод тоже не хочется

Гениус чето совсем не по теме вроде.

посоветовали мне тут уже два человека юзать Vector.
запихну его в родительский класс и попробую)

jimon 27.06.2009 23:56

Ответ: Хитрая хитрость
 
Genius
о static_cast слышал ?
если уж у тебя так получилось (кривая архитектура или что-то еще) то можно и dynamic_cast использовать

Mr_F_
просто представь что у тебя нету понятия индекс переменной, компилятор переменную которая у тебя написана второй может сделать первой или третей
программируй так чтобы тебе индекс переменной был не нужен

Genius 27.06.2009 23:58

Вложений: 1
Вот ещё немного расширил:
Код:

class Car;
class Human;

static std::vector<GameObject*> gameWorld;

void insertGameObject( GameObject* object )
{
    gameWorld.push_back(object);
}

class GameObject
{
public:
    float x,y,z,pitch,yaw,roll;
    bool alive;

    GameObject(){ insertGameObject(this); }
    virtual ~GameObject(){}

    bool isAlive() { return alive; }

    Car* getCar(){return 0;}
    Human* getHuman(){return 0;}

    virtual void setPosition(float _x,float _y,float _z){ x=_x;y=_y;z=_z; }
    virtual void setOrientation(float _pitch,float _yaw,float _roll){ pitch=_pitch;yaw=_yaw;roll=_roll;}

    virtual void update(float ifps){}
};

class Car : public GameObject
{
public:
    int model;
    float max_speed;

    Car()
    {
          max_speed=0;
    }

    virtual ~Car()
    {
        xFreeEntity(model);
    }

    Car* getCar(){return this;}
 
    void setPosition(float x,float y,float z)
    {
          GameObject::setPosition(x,y,z);
          ....
    }

    void setOrientation(float pitch,float yaw,float roll)
    {
        GameObject::setOrientation(pitch,yaw,roll);
        ...
    }

    void update()
    {
        car physic update...
    }
};

class Human : public GameObject
{
public:

    int health;
    int model;

    Human()
    {
        model = xLoadAnimMesh("human.b3d");
        health=100;
    }

    ~Human()
    {
        xFreeEntity(model);
    }

    Human* getHuman(){return this;}
 
    void setPosition(float x,float y,float z)
    {
          GameObject::setPosition(x,y,z);
          ....
    }

    void setOrientation(float pitch,float yaw,float roll)
    {
        GameObject::setOrientation(pitch,yaw,roll);
        ...
    }

    void update(float ifps)
    {
        if(health <= 0)alive=false;
    }
};

class CarDriver : public Human
{
....
};

void updateGameWorld(float ifps)
{
        for(unsigned int i = 0; i < gameWorld.size(); i++)
        {
              GameObject* obj = gameWorld[i];
              if(obj->isAlive())
              {
                    obj->update(ifps);
              }
        }
}

....

GameObject* car = new Car();
GameObject* human = new Humman();

if(car->getCar() != 0)car->setPosition(40,10,0);
if(human->getHuman() != 0)human->setPosition(40,15,0);

while(!xKeyDown(1))
{
....
updateGameWorld(deltaTime);
xUpdateWorld(deltaTime);
xRenderWorld();
}

Цитата:

Сообщение от Mr_F_ (Сообщение 109276)
не, xyz у меня тут случайно совпали, в реале могут быть абсолютно разные штуки там)

говнокод тоже не хочется

Гениус чето совсем не по теме вроде.

посоветовали мне тут уже два человека юзать Vector.
запихну его в родительский класс и попробую)

А что мешает юзать Вектор,так даже удобнее,я просто изначально по твоему посту сделал xyz.

А вообще тогда бы было что-то типа

void Car::setPosition(const Vector& pos)
{
position = pos;
бла бла бла,ставим тело в позицию...
А вообще невижу смысла сохранять позицию так как есть же фунекции типа xPositionEntity,pxBodyPosition,xEntityX,pxBodyPosi tionX,etc.
}

Вот те многофункциональный 3D Вектор :)

FDsagizi 28.06.2009 00:05

Ответ: Хитрая хитрость
 
В серьёз не воспринемай =), да и пожалуй так не делай )))

Код:

struct XYZ{        float x,y,z;};

struct c1{
        char buffer[12]; // sizeof(  xyz )
        // ...
};

void main(){
        // Тут типа наш вектор
        XYZ mx;
        //Тут классик
        c1 c;
        // А вот так мы передаём данные вектора
        memcpu( &c, (void*)&mx, sizeof( XYZ );
}


Horror 28.06.2009 01:46

Ответ: Хитрая хитрость
 
Извuниете что я тут со своим мылом. у меня вопрос к Гениус)
нах так писать?
Код:

class A
{
 B* GetB()..
 C* GetC()..
};
class B :pub A{...};
class C :pub A{...};

А если еще надо детишек от А то это ты там будеш еще методы Get писать?

я конечно нубокодер)
но мне кажется на худой конец можно просто в родителя добавить переменную тип
а у детей типы разные писать )

Genius 28.06.2009 02:03

Ответ: Хитрая хитрость
 
Цитата:

Сообщение от Horror (Сообщение 109283)
Извuниете что я тут со своим мылом. у меня вопрос к Гениус)
нах так писать?
Код:

class A
{
 B* GetB()..
 C* GetC()..
};
class B :pub A{...};
class C :pub A{...};

А если еще надо детишек от А то это ты там будеш еще методы Get писать?

я конечно нубокодер)
но мне кажется на худой конец можно просто в родителя добавить переменную тип
а у детей типы разные писать )

Да буду добавлять,так-как это делается для проверки,откуда ты знаеш что GameObject* car - является классом Car? Эти Get'ы тоже самое что в блице делать проверку EntityClass(ent) == "Mesh"... Только удобнее.

Я не говорю что это униврсальный способ,и для игры где претпологается динамическое добавления новых типов игровых объектов,через скрипт,ini,и т.д он точно не подходит,а вот если все игровые объекты буду описаны кодом то это вполне удобное решение.

Mr_F_ 28.06.2009 03:21

Ответ: Хитрая хитрость
 
Цитата:

просто представь что у тебя нету понятия индекс переменной, компилятор переменную которая у тебя написана второй может сделать первой или третей
программируй так чтобы тебе индекс переменной был не нужен
а где интересно было понятие индекс переменной?) конечно его нигде нет, я пишу:
Цитата:

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

ща объясню зачем всё надо)

у меня есть свой формат файла (левел). раньше он состоял из готовых блоков с четко заданой последовательностю и структурой. но потом я стал запариваться, когда нужно было ввести какой то новый параметр в один из видов объектов, или вообще новый вид объекта. старый загрузчик сбивался и грузил черти что, надо было аккуратно менять сначала только сохранение, потом пересохранять все имеющиеся карты, затем менять лоад и тогда только радоваться).
я решил сделать формат файла как бы параметр-driven. аналогичное наблюдается в формате FBX. структура такова:

объект
{
номер значения
значение
}

"номер значения-значение" конечно может быть много, до 255.
их структура выглядит так:

B номер значения
B тип данных
сами данные

(B - байт, тип данных от 1 до 5, соотв от байта до стринга).

а заголовок "объекта" представляет собой:

B тип объекта (номер класса, тут проверяем просто ифом, их немного)
L кол-во впереди идущих параметров со значениями

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

вышеуказанный стиль формата файла имхо может весьма сократить расход нервов и сделать вполне совместимыми файлы разных версий (не хватает инфы? игнорим!)

Genius 28.06.2009 03:55

Ответ: Хитрая хитрость
 
Ёпть так надо было сразу с этого начинать...

Я бы так делал:

Мы уже имеем объекты:

представим что у нас в объекте есть массив так называемых Value,Value имеет 2 переменые 1) int,индификатор типа данных которые содержатся в Value и данные void*,

Код:

struct Value
{
    enum{
      INT=1,
      FLOAT,
      BOOL,
      STRING
    };
    char type;
    void* data;

    void setInt(int v)
    {
        type = INT;
        data = &v;
    }
    void setFloat(flaot v)
    {
        type = FLOAT;
        data = &v;
    }
    void setBool(bool v)
    {
        type = BOOL;
        data= &v;
    }
    void setString(char* str)
    {
        type = STRING;
        data=str;
    }

    int toInt()
    {
      return *static_cast<int*>(data);
    }
    float toFloat()
    {
      return *static_cast<float*>(data);
    }
    bool toBool()
    {
      return *static_cast<bool*>(data);
    }
    char* toString()
    {
      return static_cast<char*>(data);
    }

    bool isINT()
    {
      return type == INT;
    }
    bool isFLOAT()
    {
      return type == FLOAT;
    }
    bool isBOOL()
    {
      return type == BOOL;
    }
    bool isSTRING()
    {
      return type == INT;
    }
};

struct Object
{
    char id; // индификатор 0-225
    std::vector<Value> values;
};


пишем в файл кол-во объжектов
for(int i=0;i<count_objects;i++)
{
    Object* obj = objects[i];
    пишем в файл char  - obj->id;
    пишем в файл int - obj->values.size(); - кол-во value'ев
    for(int k=0;k<obj->values.size();k++)
    {
          Value val = obj->values[k];
          пишем char val->type; - тип value
          switch(val->type)
          {
              case Value::INT:
              {
                  пишем int - val->getInt();
              }break;
              case Value::FLOAT:
              {
                  пишем float - val->getFloat();
              }break;
              case Value::BOOL:
              {
                  пишем bool - val->getBool();
              }break;
              case Value::STRING:
              {
                  пишем char* - val->getString();
              }break;
          }
    }

}

Загрузка аналагично записи.
Еесли будет не понятно могу и пример загрузки этого чуда написать..

Mr_F_ 28.06.2009 04:41

Ответ: Хитрая хитрость
 
спасибо всем!
вроде тут сам успел допереть как то)

сделал так:

родительский класс:
Код:

class access
{
public:
        int **ivec;
        bool **bvec;
        float **fvec;
        string **svec;
};

дочерний (начало):

Код:

class material:public access{
private:
float alpha, brightness, contrast,...

конструктор дочернего класса (Начало):
(биндим к массиву содержимое объекта класса))
Код:

material::material()
{
       
        svec = new (string*[3]);
        fvec = new (float*[16]);
        bvec = new (bool*[25]);

                fvec[0]=&alpha;
                fvec[1]=&brightness;
                fvec[2]=&contrast;

загрузка:
Код:

        access *Temp;


        while (!myfile.eof())
        {
                objtype=readbyte(&myfile);
               
                if (objtype==1) {
                        material *mat=new material; tempname="materials"; time=int(clock());
                        Temp = mat;

                }
               
                params=readlong(&myfile);
               
                        for(p=0;p<params;p++)
                        {
                                paramnum=readbyte(&myfile);
                                paramlen=readbyte(&myfile);

                                        if (paramlen==1) *(Temp->bvec[paramnum-1])=bool(readbyte(&myfile));
                                        if (paramlen==2) *(Temp->ivec[paramnum-1])=(readshort(&myfile));
                                        if (paramlen==3) *(Temp->ivec[paramnum-1])=(readlong(&myfile));
                                        if (paramlen==4) *(Temp->fvec[paramnum-1])=(readfloat(&myfile));
                                        if (paramlen==5) *(Temp->svec[paramnum-1])=(readstringf(&myfile));

                        }

                time=int(clock())-time;
                cout << tempname << " loaded in " << time << "ms." << endl;
        }

}


jimon 28.06.2009 11:38

Ответ: Хитрая хитрость
 
Mr_F_
я сделал проще немного, у меня в файле содержится имя переменной и её значение
в программе где нужно я просто получаю значение по имени
таким образом если переменной не было то вернётся default значение :)


Часовой пояс GMT +4, время: 12:10.

vBulletin® Version 3.6.5.
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Перевод: zCarot