Problem ze statyczną składową klasy

0

Witam, to mój pierwszy post tutaj więc proszę o wyrozumiałość.
Mam klasę* Okno* która ma składową statyczną (static) - wskaźnik stały (const) na obiekt klasy sf::RenderWindow .

\\Plik Okno.h
#include <SFML/Graphics.hpp>
#ifndef OKNO_H
#define OKNO_H

class Okno              //okna w grze (og)
{
    int posX, posY;                         //wspólrzedne lewego górnego rogu og
    int width, height;                      //szerokosc i wysokosc og
    static sf::RenderWindow * const wskOkna;       //wsk na obiekt okna aplikacji

public:
    Okno(  int = 400, int = 150 );
    void rysujOkno();                       //rysowanie okna
};

#endif

Chcę inicjalizować ten wskaźnik adresem obiektu window. Definicja obiektu window jest w pliku main.cpp stąd extern. Wyskakuje mi błąd undefined reference to `window' w ostatniej załączonej linii, przy próbie wywołania metody draw obiektu wskazywanego przez wskaźnik.

\\Plik Okno.cpp
#include "Okno.h"

extern sf::RenderWindow window;
sf::RenderWindow * const Okno::wskOkna = &window;

Okno::Okno( int w, int h )
{
    posX = 40;
    posY = 40;
    width = w;
    height = h;
}

void Okno::rysujOkno() //rysuje okno w grze
{
    int rozmiarElRamki = 22; //rozmiar kafelka w sprajcie
    sf::Texture tekstura;
    tekstura.loadFromFile( "okno.png" );

    sf::Sprite obraz;
    obraz.setTexture( tekstura );
        // rysowanie lewego górnego rogu okna
    obraz.setTextureRect( sf::IntRect( rozmiarElRamki * 2, rozmiarElRamki, rozmiarElRamki, -rozmiarElRamki ) );
    obraz.setPosition( sf::Vector2f( posX, posY ) );
    wskOkna->draw( obraz );                              // <<--- TU Pokazuje błąd
    ...
}

Proszę o podpowiedź co robię nie tak. Wskaźnik poprawnie pokazuje na obiekt window bo CodeBlocks widzi składowe tego obiektu. Skąd więc taki błąd?
Dodam, że wcześniej klasa wyglądała inaczej, tzn wskaźnik nie był statyczny i jednocześnie był inicjalizowany poprzez argument w konstruktorze. Wtedy zarówno metoda draw jak i cała funkcja rysujOkno mi działała.

0

Wszystkie obiekty klasy Okno mają odnosić się do tego samego obiektu window, dlatego chcę żeby był statyczny. Obiekt na który pokazuje wskaźnik nie jest globalnym, jego deklaracja jest, jak napisałem wcześniej, w funkcji main w innym pliku main.cpp, którego treści tutaj nie załączałem.

1

Jeśli zdefiniowałeś window w funkcji main, to nie dziwne, że kompilator krzyczy Ci o braku definicji. Dałeś deklarację z extern, co sugeruje, że odwołujesz się do zmiennej globalnej (external linkage) zdefiniowanej w innej jednostce kompilacji. Zmienne lokalne, jak sama nazwa wskazuje, nie są zmiennymi globalnymi :)

Zrób statyczną metodę setWindow, która ustawia wskaźnik wskOkna, i wywołaj ją w funkcji main po stworzeniu obiektu window.

0

Dzięki za odpowiedź. Chcę zrobić tak jak napisałeś ale mi nie działa.
Jest w nagłówku klasy Okno składowa statyczna wskOkna typu sf::RenderWindow, oraz metoda statyczna setWindow. W źródle klasy definiuję tą metodę i w jej ciele chcę przypisać do znacznika wskOkna adres obiektu window. Kompilator wypisuje mi błąd undefined reference to `Okno::wskOkna'. Dodatkowo pisze error: 1d returned 1 exit status. Czytałem, że ten drugi błąd związany jest z niezamkniętym procesem poprzednio uruchomionego programu, jednak to nie to.

//plik Okno.h
#include <SFML/Graphics.hpp>
#ifndef OKNO_H
#define OKNO_H

class Okno              //okna w grze (og)
{
    int posX, posY;                         //wspólrzedne lewego górnego rogu og
    int width, height;                       //szerokosc i wysokosc og
    static sf::RenderWindow * wskOkna;       //wsk na obiekt okna aplikacji
public:
    Okno( int = 400, int = 150 );
    static void setWindow( sf::RenderWindow * );
    void rysujOkno();
};
#endif
//Plik Okno.cpp
void Okno::setWindow( sf::RenderWindow * wsk )
{
    wskOkna = wsk;              // <<-- Tu pokazuje błąd
}
//Plim main.cpp
#include "Okno.h"

int main ()
{
    sf::Vector2i screenRes (800, 600);
    sf::RenderWindow window;
    window.create( sf::VideoMode( screenRes.x, screenRes.y ), "Moje okno" );

    Okno::setWindow(&window);
    Okno okienko( 500, 270 );

    sf::Event zdarzenie;
    while ( window.isOpen() )
    {
        while( window.pollEvent(zdarzenie) )
        {
            if ( zdarzenie.type == sf::Event::Closed )
            {
                window.close();
            }
        }
        window.clear();
        okienko.rysujOkno();
        window.display();
    }
}

1

A definicja sf::RenderWindow* Okno::wskOkna = nullptr; jest?

0

Dzięki, teraz działa:) W książce (Symfonia C++) nic na ten temat nie było. Pisało tylko o koniecznej definicji poza klasą składnika statycznego (nie metody), przy metodzie nic nie pisało więc wydawało mi się że być nie musi. Na przykładach znajdowanych na forach też nikt takiej definicji nie używał. Poczytam o tym więcej.

Zauważyłem teraz dopiero jaką głupotę napisałem. Przecież to jest definicja tego wskaźnika :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1