Skocz do zawartości

[C++]Problemy podczas wypełniania instancjami objektu tablicy wskaźników


RaistlinBlackRobe

Rekomendowane odpowiedzi

Witam.

Ostatnio pojawił się u mnie pewien problem, którego pomimo usilnych starań nie udało mi się rozwiązać. Błędy, które się pojawiły kompletnie mnie zaskoczyły.

Sprawa wygląda następująco:

 

Mam w projekcie 3 pliki: main.cpp, main.h, obj.h

 

main.cpp:

#include "main.h"
#include "obj.h"

bool init=1;
obj_hero* inst_hero = new obj_hero;
obj_block* inst_block[2];                    //tworzymy tablicę wskaźników na klasę obj_block        
int inst_block_count = 2;                    //zmienna przechowująca ilość elementów danej tablicy

int g_main()
{
    if (init)                                          //instrukcje tworzenia instancji
    {
          unsigned x_rand;
          unsigned y_rand;
          for(int i=0; i<inst_block_count; i++)
         {
                 inst_block[i]= new obj_block;
                 srand(time(NULL));
                 do
                 {
                          x_rand=floor(rand()%32);
                          y_rand=32 - ceil(rand()%32);
                 } while(grid_state[x_rand][y_rand]!=GRID_FREE);
                 inst_block[i]->x_grid=x_rand;
                 inst_block[i]->x=inst_block->x_grid+0.5*inst_block->a;
                 inst_block[i]->y_grid=y_rand;
                 inst_block[i]->y=inst_block->y_grid+0.5*inst_block->a;
                 grid_state[x_rand][y_rand]=GRID_BLOCK;
         };
        init=0;
    };
    //w tym miejscu ustawianie kamery i eventy
    return 0;
};

Tytułem wyjaśnienia:

-funkcja g_main() jest funkcją, której prototyp znajduje się w main.h i jest wywoływana w głównej pętli

-grid_state[][] to tablica enumów, określa co się znajduje na danym polu

 

main.h:

W nim znajdują się #includy, deklaracje zmiennych globalnych, definicje procedury okienkowej i WinMaina.

 

obj.h:

Tutaj mam definicje wszystkich klas i ich metod.

 

Komunikaty błędów:

'srand' undeclared (first use this function)

'rand' undeclared (first use this function)

'ceil' undeclared (first use this function)

'floor' undeclared (first use this function)

'x_grid' has not been declared

request for member of non-aggregate type befor '+' token

 

i jeszcze szereg takich samych błędów dotyczących kolejnych zmiennych...

 

Czy ktoś może wie, co zrobiłem nieprawidłowo? Zaznaczam, że odpowiednie nagłówki dodałem. Z góry dzięki.

Odnośnik do komentarza
Udostępnij na innych stronach

po pierwsze to nie zainkludowałeś biblioteki math.h. w ogóle coś nie teges to wygląda, zrobię sobie herbatę i dopisze zaraz co mam na mysli ;)

Odnośnik do komentarza
Udostępnij na innych stronach

w takim razie podaj dokladna tresc bledow, tj. ze sciezka wzgledna do plikow, bo albo masz gdzies wczesniej uzyte te funkcje niz zainkludowales ich biblioteki albo masz kilka plikow cpp i nie kazdemu inkludujesz.

Swoja droga, opisz mniej wiecej jak dziala Twoj program (opisowo co sie dzieje po kolei) bo mam pare rozwiazan ktore oducza Cie zlych nawykow ;p

Odnośnik do komentarza
Udostępnij na innych stronach

Błedy wyskakują w pliku main.cpp, w funkcji g_main(), w środku konstrukcji warunkowej if (init), czyli odnoszą się do właśnie tych instrukcji tworzenia objektów i przypisywania ich polom pewnych wartości. Odwoływanie się do konkretnej linijki nie ma sensu, bo wyciąłem i wkleiłem tutaj to co trzeba było. Jak już zaznaczyłem funkcja g_main() jest wywoływana w środku pętli głównej programu, w nagłówku main.h w funkcji WinMain(), a includy są naturalnie wcześniej.

EDIT:

Mam jeden plik .cpp.

Działanie funkcji g_main():

-Przy pierwszym obiegu pętli wypełnia tablice wskaźników świeżutkimi objektami i (jeśli trzeba to zrobić tu) nadaje im wartości początkowe.

-Wykonuje metodę event_step() każdej instancji która ją posiada. Zbieżności nazw z gmowymi nieprzypadkowe.

-glClear(...);

-glEnable(GL_DEPTH_TEST);

-Ustawienia kamery za pomocą gluLookAt(...);

-Rysowanie podłoża.

-Wykonuje metodę event_draw() każdej instancji.

Odnośnik do komentarza
Udostępnij na innych stronach

a czy srand nie jest przypadkiem z stdlib? zapodaj jakie includy masz

Odnośnik do komentarza
Udostępnij na innych stronach

#define WIN32_LEAN_AND_MEAN

 

#include <windows.h> //nagłówek windows

 

#include <gl/glaux.h>

#include <ctime>

#include <math.h>

 

srand() i rand() są z <ctime>, przynajmniej dotychczas tak ich używałem.

 

Moja edycja minęła się z twoim postem, więc umieszczam ponownie opis działania:

-Przy pierwszym obiegu pętli wypełnia tablice wskaźników świeżutkimi objektami i (jeśli trzeba to zrobić tu) nadaje im wartości początkowe.

-Wykonuje metodę event_step() każdej instancji która ją posiada. Zbieżności nazw z gmowymi nieprzypadkowe.

-glClear(...);

-glEnable(GL_DEPTH_TEST);

-Ustawienia kamery za pomocą gluLookAt(...);

-Rysowanie podłoża.

-Wykonuje metodę event_draw() każdej instancji.

 

EDYCJA:

 

Na <cstdlib>ie poszły te funkcje.

To uczyniło teraz problem już stricte dotyczący tworzenia instancji. Rzecz w tym, że dalej nie potrafi się odwołać do pól tych objektów i wygląda to tak, jak gdyby nie zostały one stworzone.

inst_block[i]= new obj_block;

Czy ta linijka jest źle napisana?

Odnośnik do komentarza
Udostępnij na innych stronach

zalezy. podaj definicje klasy obj_block

Odnośnik do komentarza
Udostępnij na innych stronach

Definicja klasy:

class obj_block //klasa objektu przeszkody
{
      public:
             float x;
             float y;
             int x_grid;         //kratka x, w której się znajduje
             int y_grid;         //kratka y, w której się znajduje
             int z;
             float a;            //długość boku
             float h;            //wysokość
             obj_block();        //konstruktor
             int event_draw();   //rysowanie objektu
};
obj_block::obj_block():
x (4.0f),
y (4.0f),
x_grid (0),
y_grid (0),
z (0.0f),
a (8.0f),
h (8.0f)
{
};

int obj_block::event_draw()
{
    glPushMatrix();
    glTranslatef(x, y, z+0.5*h);
     glRotatef(0.0f, 1.0f, 1.0f, 1.0f);    //ustawiamy obrót na jego brak
     glBegin(GL_QUADS);                     //rysujemy 6 ścian
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(-0.5f*a, -0.5f*a, -0.5f*h); //-z
        glColor3f(0.75f, 0.25f, 0.0f);
       glVertex3f(0.5f*a, -0.5f*a, -0.5f*h);
        glColor3f(0.75f, 0.0f, 0.0f);
       glVertex3f(0.5f*a, 0.5f*a, -0.5f*h);
        glColor3f(0.5f, 0.5f, 0.0f);
       glVertex3f(-0.5f*a, 0.5f*a, -0.5f*h);
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(-0.5f*a, -0.5f*a, 0.5f*h); //z
        glColor3f(0.75f, 0.25f, 0.0f);
       glVertex3f(0.5f*a, -0.5f*a, 0.5f*h);
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(0.5f*a, 0.5f*a, 0.5f*h);
        glColor3f(0.5f, 0.5f, 0.0f);
       glVertex3f(-0.5f*a, 0.5f*a, 0.5f*h);
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(0.5f*a, 0.5f*a, -0.5f*h); //x
        glColor3f(0.75f, 0.25f, 0.0f);
       glVertex3f(0.5f*a, -0.5f*a, -0.5f*h);
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(0.5f*a, -0.5f*a, 0.5f*h);
        glColor3f(0.5f, 0.5f, 0.0f);
       glVertex3f(0.5f*a, 0.5f*a, 0.5f*h);
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(-0.5f*a, 0.5f*a, -0.5f*h); //-x
        glColor3f(0.75f, 0.25f, 0.0f);
       glVertex3f(-0.5f*a, -0.5f*a, -0.5f*h);
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(-0.5f*a, -0.5f*a, 0.5f*h);
        glColor3f(0.5f, 0.5f, 0.0f);
       glVertex3f(-0.5f*a, 0.5f*a, 0.5f*h);
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(0.5f*a, 0.5f*a, -0.5f*h); //y
        glColor3f(0.75f, 0.25f, 0.0f);
       glVertex3f(-0.5f*a, 0.5f*a, -0.5f*h);
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(-0.5f*a, 0.5f*a, 0.5f*h);
        glColor3f(0.5f, 0.5f, 0.0f);
       glVertex3f(0.5f*a, 0.5f*a, 0.5f*h);
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(0.5f*a, -0.5f*a, -0.5f*h); //-y
        glColor3f(0.75f, 0.25f, 0.0f);
       glVertex3f(-0.5f*a, -0.5f*a, -0.5f*h);
        glColor3f(1.0f, 0.0f, 0.0f);
       glVertex3f(-0.5f*a, -0.5f*a, 0.5f*h);
        glColor3f(0.5f, 0.5f, 0.0f);
       glVertex3f(0.5f*a, -0.5f*a, 0.5f*h);
     glEnd();                             //kończymy rysować
     glPopMatrix();
     return 0;
};

Deklaracja tablicy inst_block:

obj_block* inst_block[2];

Odnośnik do komentarza
Udostępnij na innych stronach

hmm, nader dziwne. skoro masz tylko 1 plik cpp i definicje g_main() po definicji klasy obj_block to musi dzialac. na sucho raczej nie pomoge, za duzo niewiadomych. zapodaj projekt jak mozesz na pw, sprawdze na zywo co nie gra.

Odnośnik do komentarza
Udostępnij na innych stronach

hmm, nader dziwne. skoro masz tylko 1 plik cpp i definicje g_main() po definicji klasy obj_block to musi dzialac. na sucho raczej nie pomoge, za duzo niewiadomych. zapodaj projekt jak mozesz na pw, sprawdze na zywo co nie gra.

 

Sęk w tym, że jak ma się czegoś nauczyć to takie praktyki raczej nie są dobrym rozwiązaniem.

Odnośnik do komentarza
Udostępnij na innych stronach

zwykle poza sprawdzaniem tlumacze tez co jest zle wiec jednak sie czegos nauczy ;p

Odnośnik do komentarza
Udostępnij na innych stronach

łojć. ale wiedz że nie każdy ma te same biblioteki co Ty, chodzi o to że muszę to (spróbować) skompilować, aby dostać błędy, a tak to niewiele mogę :P

Odnośnik do komentarza
Udostępnij na innych stronach

Masz paskudny styl pisania. Polecam przeczytać jakąkolwiek książkę o c++ lub programowaniu obiektowym. W przeciwnym wypadku już przy kodzie 2k+ będziesz miał armagedon. No i podawaj treść błędów i jak już dajesz kod do poprawy dawaj cały projekt.

Odnośnik do komentarza
Udostępnij na innych stronach

No tak biblioteki. Wybaczcie. Linkuję te:

-libopengl32.a

-libglu32.a

-libglaux.a

@Will:

Wprawdzie przytaczałem je już, ale zrobię to ponownie:

'x_grid' has not been declared

request for member of non-aggregate type before '+' token

`a' has not been declared

request for member of non-aggregate type before ';' token

`y_grid' has not been declared

request for member of non-aggregate type before '+' token

`a' has not been declared

request for member of non-aggregate type before ';' token

 

Co dokładnie w moim pisaniu jest paskudne(jezeli chodzi o pisanie ręczne to się zgadzam)? Wiesz, to pewnie w dużej mierze zależy od osoby. Dla mnie akurat taki styl jest przejrzystszy od innych(np. nie lubię bardzo nazw funkcji, w których kolejne wyrazy są oddzielone dużą literą, podkreślenie jest dużo czytelniejsze).

Odnośnik do komentarza
Udostępnij na innych stronach

Przykładowa klasa:

 

/**

*/
    class WindowMgr:public Singleton<WindowMgr>
    {
    public:

        /**

        */
inline    wID addWindow(RenderWindow* pWnd);
        /**

        */
inline    void removeWindow(RenderWindow* pWnd);
        /**

        */
inline    void removeWindow(const std::string& sName);
        /**

        */
inline    void removeWindow(wID id);
        /**

        */
inline  void addWindowEventListener(RenderWindow* pWnd,WindowEventListener* pListener);
        /**

        */
inline    void addWindowKeyboardListener(RenderWindow* pWnd,WindowKeyboardListener* pListener);
        /**

        */
inline    void addWindowMouseListener(RenderWindow* pWnd,WindowMouseListener* pListener);
        /**


        */
        void messagePump();
        /**

        */
        LRESULT WndProcedure(HWND hWnd,UINT msg, WPARAM wParam, LPARAM lParam);


        /**

        */
        void removeAllWndBut(RenderWindow* pWnd);
        /**

        */
        void removeAll();
        /**

        */
inline    uint GetWndCount() const;
        /**

        */
        WNDPROC GetWndProc() const;

    private:

        /*###########################################*/

        /*
            inner class
        */
        class WndHolder
        {

        public:
         //
         WndHolder(RenderWindow* Wnd);
         //
         ~WndHolder();

         RenderWindow* pWnd;
         std::list<WindowEventListener*> m_WndEvents;
         std::list<WindowKeyboardListener*> m_KeyboardEvents;
         std::list<WindowMouseListener*>    m_MouseEvents;
         //
         wMouseState m_MouseState;


         static bool Compare(const WndHolder holder,const RenderWindow* pWnd);

         /*
         */
         bool operator==(const RenderWindow* pWnd);
        };
        /*#############################################*/



        std::vector<WndHolder> m_vWindows;


        /*
        */
    inline    WndHolder* FindHolder(RenderWindow* pWnd);
        /*
        */
    inline  WndHolder* FindHolder(HWND hwnd);


        
        };

 

 

/*---------------------------------------------------------------------------------------------------------

                                WindowMgr::FindHolder()

----------------------------------------------------------------------------------------------------------*/
WindowMgr::WndHolder* WindowMgr::FindHolder(HWND hwnd)
{
    std::vector<WndHolder>::iterator it=m_vWindows.begin();
    while(it!=m_vWindows.end())
    {
        if(it->pWnd->GetHandle()==hwnd)return &(*it);
        ++it;
    }
    return NULL;
}

 

 

 

 

 

Przede wszystkim wiesz po co są klasy? Używasz ich jak pojemników to nie C.

Odnośnik do komentarza
Udostępnij na innych stronach

No cóż.

Jednym z podstawowych elementów składających się na moje cele, tudzież sposoby uzywania klas wynikają z mojego rozumienia objektów(nie chodzi mi o objekty w samym sensie informatycznym, tylko po prostu o objekty, o rozumienie tego słowa). Jezeli chodzi o to, że masz mi za złe, że nie używam w bieżącym momencie czasu wszystkich dobrodziejstw klas(dziedziczenie, funkcje wirtualne, polimorfizm itd.), to wynika to z małej zaawansowaności aplikacji. Uzycie ich jest tutaj kwiestią czasu, mam rozplanowane w miarę ich uzycie(oczywiście nie bezcelowe, na pokaz, tylko słuszne i ułatwiające wiele rzeczy).

Odnośnik do komentarza
Udostępnij na innych stronach

Jakich dobrodziejstw? To nawet nie jest klasa tylko PODS'y, które nic z klasami nie mają wspólnego. Powinieneś chociaż używać metod dostępowych, które pozwolą innym zrozumieć twój kod i znaleźć błąd bez błądzenia po masie niespójnego i nieprzemyślnego kodu. Zaplanowane? Znaczy, że aplikacja tylko po części ma być zgodna z zasadami programowania? Jak będę miał czas przerobie twój kod i wtedy spróbuje znaleźć w nim błąd i pokaże Ci, że przestrzeganie kilku prostych zasad na prawdę ułatwia pisanie.

Odnośnik do komentarza
Udostępnij na innych stronach

 
inst_block[i]->x_grid=x_rand;
inst_block[i]->x=inst_block[i]->x_grid+0.5*inst_block[i]->a;
  inst_block[i]->y_grid=y_rand;
inst_block[i]->y=inst_block[i]->y_grid+0.5*inst_block[i]->a;

 

Twój stary kod:

inst_block[i]->x_grid=x_rand;
  inst_block[i]->x=inst_block->x_grid+0.5*inst_block->a;
inst_block[i]->y_grid=y_rand;
  inst_block[i]->y=inst_block->y_grid+0.5*inst_block->a;

 

Nie dziw się, że nikt tego nie zauważył. Pamiętaj, że twój kod to twoja wizytówka.

Odnośnik do komentarza
Udostępnij na innych stronach

Dzięki wielkie. Zawsze musze walnąć jakiś głupi, prosty błąd, ale taki, że trudno go dostrzec.

W takim razie: w jaki sposób podporządkować moje aplikacje całkowicie tym ogólnym zasadom? W tych celach, w jakich tu wykorzystałem klasy trudno byłoby mi użyć czegoś innego do uzyskania takiego samego efektu. Z drugiej strony: czy to oznacza, że zgodność z zasadami zakłada użycie pewnych rzeczy, nawet gdy nie są one tu potrzebne, czy to moja zła interpretacja?

Jezeli chodzi o metody dostępowe, to chodzi tu po prostu o metody, które zwracają jakieś pole, tak? Mógłbyś zobrazować w jaki sposób dodają czytelności kodowi?

Odnośnik do komentarza
Udostępnij na innych stronach

Efekt będzie ten sam ale będzie bardziej przejrzyście, bezpieczniej, z możliwością późniejszego rozbudowania itp.

 

 

Po pierwsze podałem deklaracje mojej klasy(Usunąłem komentarze). Wygląda czytelniej niż twoja.

Poza tym (również na przykładzie mojej klasy) według twojego myślenia dodanie listenera wyglądało by tak:

object.Windows.push_back(Listener) w moim object.addListener(Listener).

Pomijam możliwość obsługi błędów i konieczność znalezienia szukanego okna.

Druga sprawa: Załóżmy, że pewna zmienna jest tablicą nawet przykład z twojego kodu:

obj_block* inst_block[2];

Gdyby był to element klasy nie zrobiłbyś błędu gdyż element pobrałbyś metodą:

obj_block* GetObjBlock(unsigned index)

{

if(index>=m_uMaxCount)//obsluga bledu

return m_aBlocks[index];

}

 

Wtedy twoje obliczenia wyglądały by tak:

 

 

m_Object.SetXGrid(x_rand);

m_Object.setX( m_Object.getXGrid()+0.5*m_Object.getA() );

 

 

 

A my musielibyśmy co najwyżej sprawdzić definicje metod a nie babrać się w masie makaronu.

Używanie zmiennych globalnych też nie jest dobrym pomysłem. Najlepiej dane wpakować w odpowiednie klasy z odpowiednimi nazwami metod i

składowych(na pewno nie 'a'). Jest jeszcze masa innych rzeczy ale to już musisz kupić książkę i przeczytać odpowiednie rozdziały.

Odnośnik do komentarza
Udostępnij na innych stronach

Jeśli chcesz dodać odpowiedź, zaloguj się lub zarejestruj nowe konto

Jedynie zarejestrowani użytkownicy mogą komentować zawartość tej strony.

Zarejestruj nowe konto

Załóż nowe konto. To bardzo proste!

Zarejestruj się

Zaloguj się

Posiadasz już konto? Zaloguj się poniżej.

Zaloguj się
  • Ostatnio przeglądający   0 użytkowników

    • Brak zarejestrowanych użytkowników przeglądających tę stronę.
×
×
  • Dodaj nową pozycję...