Skocz do zawartości

Wskaźnik na strukturę wewnątrz siebie samej


Raalsky

Rekomendowane odpowiedzi

Witam

 

Mam strukturę "street", która oznacza ulicę. Ma właściwość jaką jest parent, czyli do jakiego "miasta" przynależy, czyli wskaźnik na strukturę "town". W strukturze "town" mam wektor wskaźników na ulice oraz metodę, która dodaje kolejne wskaźniki do tego wektora. Chciałbym, aby przy każdym dodawaniu ulicy dana ulica miała ustawianego "ojca" na strukturę town dla której została wywołana ta metoda. Brzydkim rozwiązaniem byłoby wrzucanie tego przez argumeny metody, bo podobne metody mam jeszcze przy kilku strukturach. Poszukuję czegoś typu "this" z klas, ale dla struktur.

 

struct town;

struct street {
    town * parent;
};

struct town {
    vector<street *>streets;
    void push_street( street * p ) {
        streets.push_back( p );
        p->parent = WSKAŹNIK NA AKTUALNĄ STRUKTURĘ
    }
}

Odnośnik do komentarza
Udostępnij na innych stronach

Jedyną różnicą między klasą a strukturą w c++ jest domyślny specyfikator dostępu, więc różnicy nie ma.

Struct ma też wskaźnik this, tak samo jak class, więc w czym problem?

#include <vector>

struct town;

struct street {
    town* parent;
};

struct town
{
    std::vector<street*> streets;
    void push_street(street* p)
    {
        streets.push_back(p);
        p->parent = this;
    }
};

Odnośnik do komentarza
Udostępnij na innych stronach

Używam Code::Blocks z kompilatorem GCC i nie ma problemów.

Jeszcze przykładowy kod prezentujący, że powyższa metoda działa:

//bla bla
#include <iostream>
using namespace std;
//bla bla

int main()
{
    town a;
    cout << &a << endl;
    a.push_street(new street);
    cout << a.streets.back()->parent << endl;
};

 

Konsola pokaże dwa takie same adresy.

Odnośnik do komentarza
Udostępnij na innych stronach

Okej, problem leży trochę w innym miejscu. Daję pełny kod:

#include <iostream>
#include <vector>

using namespace std;

//Opakowanie strutkur w przestrzeń nazw "world"

namespace world {
    //Preinformowanie kompilatora o użytych strukturach
    struct stTown;
    struct stHouse;
    struct stMan;

    //Struktura ulicy
    struct stStreet {
        //Nazwa ulicy
        string name;
        //Wektor wskaźników na domy
        vector<stHouse *>house;
        //Miasto do którego przynależy
        stTown * parent;

        //Konstruktor
        stStreet( string tName , stTown * p = NULL ) {
            name = tName;
            parent = p;
        };
    };

    //Typ do przechowywania informacji o płci danej osoby
    enum enSex { MALE , FEMALE };

    //Struktura miasta
    struct stTown {
        //Każde miasto ma swoją nazwę np. "Warszawa"
        string name;
        //Wektor wskaźników na ulice
        vector<stStreet *>street;

        //Konstruktor
        stTown ( string tName ) {
            name = tName;
        };
        //Dodawanie ulicy
        void push_street( stStreet * p ) {
            street.push_back( p );
            street.back()->parent = this;
        }
        //Usuwanie ulicy
        void pop_street( stStreet * p ) {
            vector<stStreet *>::iterator it;
            int i;

            for( i=0; i<street.size(); i++ ) {
                if( street[i] == p )
                    break;
            }

            it = street.begin()+i;
            street.erase(it);
        }
    };

    //Struktura domu
    struct stHouse {
        //Numer domu
        int number;
        //Wektor wskaźników na mieszkańców
        vector<stMan *>in;

        //Konstruktor
        stHouse( int tNumber ) {
            number = tNumber;
        };
    };

    //Struktura mieszkańca
    struct stMan {
        //Płeć
        enSex sex;
        //Wiek
        int age;
        //Imię
        string firstname;
        //Nazwisko
        string lastname;
        //Dom
        stHouse * home;

        //Konstruktor
        stMan( string tFirstname , string tLastname , int tAge , enSex tSex ) {
            firstname = tFirstname;
            lastname = tLastname;
            age = tAge;
            sex = tSex;
        };
        //Przyłącz do domu
        void bind( stHouse * p ) {
            home = p;
            stMan * c = this;
            p->in.push_back( c );
        };
    };

    //Globalne wektory zawierające same struktury
    vector<stTown>gTown;
    vector<stStreet>gStreet;
    vector<stHouse>gHouse;
    vector<stMan>gMan;
};

 

Problem leży po stronie kolejności definiowania struktur itp. Gdy chcę się odwołać do właściwości, która jeszcze nie istnieje, ale mam zdefiniowany "nagłówek" struktury to kompilator wywala błąd. Ehh, dość ciężkie było do znalezienia.

Odnośnik do komentarza
Udostępnij na innych stronach

asddd.png

Kompilacja przebiega pomyślnie. Jedyne, co zrobiłem, to dodanie funkcji main.

Jaka jest treść tego błędu?

 

 

PS. Jeszcze coś, do czego bym się przyczepił:

void push_street( stStreet * p ) {

street.push_back( p );

street.back()->parent = this;

}

Po co tak? :P Trochę naokoło. Nie lepiej zrobić

p->parent = this;
street.push_back(p);

?

 

No i kolejna sprawa, tak jak mówił Tymon - używaj klas. Oczywiście na upartego możesz używać struktur, tylko w odpowiednich miejscach wstaw specyfikatory private/public/protected. Chodzi o bezpieczeństwo - wszystkie elementy klasy, które mogą być prywatne, powinny takie być. Dostęp do nich udzielaj metodami.

Odnośnik do komentarza
Udostępnij na innych stronach

Ja nie mówię, że to źle działa. Problem nie był z samym "this", ale z kolejnością definiowania struktur. Podałem poprawnie działający kod. Problem jest taki:

struct a;
struct b {
    a * parent;
    void bla( a * p ) {
        p->val = 4;
    };
};
struct a {
    int val;
    b * son;
}

 

I tutaj będzie problem. Bo, aby uniknąć problemów to najpierw definiuję tylko "wspomnienie" o strukturze A. Potem W strukturze B używam wskaźnika na A oraz mam metodę, która używa jakiejś właściwości z A, którą dopiero definiuję później. Czy jest możliwość, aby najpierw zdefiniować tak jakby część struktury, a potem dopisać do tego całą resztę?

 

@up: spokojnie, użyłem tego szukając błędu. Poprzedni fragment wyglądał tak jak powinien "p->parent".

Odnośnik do komentarza
Udostępnij na innych stronach

struct a;
struct b {
    a* parent;
    void bla( a* p );
};
struct a {
    int val;
    b* son;
};

void b::bla(a* p)
{
    p->val = 4;
};

 

Jeśli chcesz, żeby "bla" była funkcją inline(a taką jest, kiedy definiujesz ją w środku klasy/struktury), to dopisz z przodu inline.

inline void b::bla(a* p)
{
    p->val = 4;
};

Odnośnik do komentarza
Udostępnij na innych stronach

Miodnie. Tak, wiem co oznacza inline. Znam też klasy. Po prostu zbyt mało o strukturach znalazłem materiałów i nie wiedziałem jak głęboko sięga to utożsamianie się z klasami. Znasz jakiś dobry kurs średnio zaawansowanego C++? Uczyłem się z: http://cplusplus.com/files/tutorial.pdf ,jednak przyda się jeszcze jakieś materiały.

Odnośnik do komentarza
Udostępnij na innych stronach

Nie mam porównania, bo uczyłem się tylko z jednego kursu - http://xion.org.pl/productions/texts/coding/megatutorial/

Od strony technicznej. Potem pozostaje nauka poszczególnych bibliotek(które będą Ci potrzebne) i różnych informatycznych zagadnień, już luźno związanych z samym językiem. Materiałów na internecie jest pełno, gdy zobaczysz w czyimś kodzie słówko, z którym się nie spotkałeś, po prostu wklepujesz je w google.

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ę...