Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] wskaźnik na element dwuwymiarowego vectora, znajdującego się w obiekcie danej klasy

Ostatnio zmodyfikowano 2016-03-06 23:50
Autor Wiadomość
motopompa
Temat założony przez niniejszego użytkownika
[C++] wskaźnik na element dwuwymiarowego vectora, znajdującego się w obiekcie danej klasy
» 2016-03-06 15:19:38
Witam,
mój problem jest następujący:
dana jest klasa Klasa i dwuwymiarowe tablice obiektów tej klasy: np. tablica1[4][4] i tablica2[4][4]. Każdy z obiektów zawiera dwa dwuwymiarowe kontenery przechowujące obiekty typu double: kontener1[4][4] i kontener2[4][4].
Celem jest jedna, uniwersalna funkcja: funkcja_zewnetrzna, która dla obiektów klasy Klasa dla których została wywołana modyfikuje wszystkie obiekty z wektora kontener1 lub kontener2, przy czym sama modyfikacja pojedynczej wartości jest realizowana przez funkcję: funkcja_wewnetrzna (funkcja_zewnetrzna ma tylko wybierac ktora tablice i ktory kontener modyfikujemy).
O tym, który element którego wektora będziemy modyfikować decydują obiekty przesłane do funkcji funkcja_zewnetrzna.
Poniżej fragment kodu (pomijam tworzenie obiektów, ustawianie wielkości kontenerów itp.)
C/C++
class Klasa
{
public:
    char nazwa;
    vector < vector < double > > kontener1;
    vector < vector < double > > kontener2;
    double funkcja_wewnetrzna( Klasa & obiekt_z_tab );
    void funkcja_zewnetrzna( Klasa ** tab );
}

void Klasa::funkcja_zewnetrzna( Klasa ** tab )
{
    double * wskaznik_na_element_kontenera;
    for( int a = 0; a < 4; a++ )
    {
        for( int b = 0; b < 4; b++ )
        {
            if( tab[ a ][ b ].nazwa == 'a' )
            {
                for( int c = 0; c < 4; c++ )
                {
                    for( int d = 0; d < 4; d++ )
                    {
                        if( tab[ a ][ b ].nazwa == 'a' )
                        {
                            wskaznik_na_element_kontenera = & tab[ a ][ b ].kontener1[ c ][ d ];
                        }
                        else
                        {
                            wskaznik_na_element_kontenera = & tab[ a ][ b ].kontener2[ c ][ d ];
                        }
                        wskaznik_na_element_kontenera = funkcja_wewnetrzna( tab[ a ][ b ] );
                    }
                }
            }
            else if( tab[ a ][ b ].nazwa == 'b' )
            {
                //analogia do powyzszego...
            }
        }
    }
}
double Klasa::funkcja_wewnetrzna( Klasa & obiekt_z_tab )
{
    // costam liczy...
    return( wartosc );
}
int main()
{
    //.......
    Klasa tablica1[ 4 ][ 4 ];
   
    tablica1[ 0 ][ 0 ].funkcja_zewnetrzna( tablica1 );
   
    //.....
}

.. powyższe skutkuje następującym błędem kompilatora:

error: cannot convert 'double' to 'double*' in assignment

...czyli nie pasuje mu sposób w jaki próbuję poprzez wskaźnik zmienić konkretny element w kontenerze, czyli dokładnie odniesienie do elementu z
vector < vector < double > > kontener1

poprzez wskaźnik
double * wskaznik_na_element_kontenera;

który odnoszę w następujący sposób:
wskaznik_na_element_kontenera = & tab[ a ][ b ].kontener1[ c ][ d ];

Czy ktoś z Was ma jakiś pomysł?
Pozdrawiam!
P-145627
mateczek
» 2016-03-06 16:04:12
chcesz wartość przypisać do wskaźnika
nie da się zrobić tak
C/C++
double * w = 3.14;
P-145632
motopompa
Temat założony przez niniejszego użytkownika
» 2016-03-06 16:15:53
mateczek,
oczywiście że się nie da, chyba że wskaźnik pokazuje na jakiś obiekt, np:
C/C++
double zmienna;
double * wskaznik;
wskaznik = & zmienna;
wskaznik = 3.14;
prawdopodobnie wprowadziłem Cię w błąd swoim kodem źródłowym, w którym pomyliłem się przy przeklepywaniu. Skorygowałem go. W mojej sytuacji wskaźnik, w momencie w którym przypisujemy do niego wartość, zawsze pokazuje na jakiś obiekt:
C/C++
wskaznik_na_element_kontenera = & tab[ a ][ b ].kontener1[ c ][ d ];
lub
C/C++
wskaznik_na_element_kontenera = & tab[ a ][ b ].kontener2[ c ][ d ];
P-145634
Monika90
» 2016-03-06 16:23:37
Wygląda na to że twoja wiedza a temat wskaźników i tablic jest błędna.

funkcja_zewnetrzna ma parametr typu Klasa**, a próbujesz wywołać ją z argumentem tablica1, który jest typu Klasa[4][4], to są zupełnie różne typy i nie ma żadnej szansy żeby skonwertować Klasa[4][4] do Klasa**
P-145635
motopompa
Temat założony przez niniejszego użytkownika
» 2016-03-06 16:35:06
Monika, moim zdaniem poprzez taki kod:
C/C++
funkcja( Klasa ** tab ) //definicja funkcji, której argumentem jest wskaźnik na dwuwymiarową tablicę
Klasa tablica1[ 4 ][ 4 ] //deklaracja tablicy dwuwymiarowej
funkcja( tablica1 ) //wrzucam całą tablica1 jako argument funkcji
przesyłam całą dwuwymiarową tablicę tablica1 do funkcji a potem wewnątrz funkcji ustawiam wskaźnik wskaznik_na_element_kontenera na któryś z elementów kontenera z któregoś obiektu z tablicy tablica1 (która cała została przesłana do funkcji).
P-145638
Kaikso
» 2016-03-06 16:36:03
Nie za bardzo rozumiem twój kod ale napisałem coś takiego może ci się przyda.

C/C++
#include <vector>

// using namespace std; // zło w czystej postaci (przeznaczone do bardziej wyrafinowanych celów)

class Klasa
{
private:
    char id; // twoja nazwa :P
    std::vector < vector < double > > kontener1;
    std::vector < vector < double > > kontener2;
   
    double & funkcja_wewnetrzna(); // to jest metoda, więc wstaśnik do obiektu klasy masz w `this'
   
public:
    static void funkcja_zewnetrzna( Klasa ** tab ); // metoda statyczna
};

int main()
{
    Klasa * tablica1[ 4 ];
    for( size_t i = 0; i < 4; i++ ) tablica1[ i ] = new Klasa[ 4 ];
   
    Klasa::funkcja_zewnetrzna( tablica1 ); // tu wywołujsz metode statyczną (funkcje w przestrzeni nazw klasy `Klasa' i z dostępem do prywatnych pój)
   
    delete[] Klasa;
    return 0;
}

void Klasa::funkcja_zewnetrzna( Klasa ** tab )
{
    for( size_t i = 0; i < 4; i++ ) for( size_t j = 0; j < 4; j++ )
    {
       
        if( tab[ i ][ j ].id == 'a' ) for( double & x
            : tab[ i ][ j ].kontener1 )
        {
            x = double & x = tab[ i ][ j ].funkcja_wewnetrzna();
        }
        else if( tab[ i ][ j ].id == 'b' )
        {
        }
    }
}

double & Klasa::funkcja_wewnetrzna()
{
    // return kontener1[ /* jakiś indeks */ ][ /* indeks następnego poziomu */ ];
}

No i oczywiście dezoriętuje mnie twoja sprzeczność w kodzie:

C/C++
void Klasa::funkcja_zewnetrzna( Klasa ** tab )
{
    double * wskaznik_na_element_kontenera;
    for( int a = 0; a < 4; a++ )
    {
        for( int b = 0; b < 4; b++ )
        {
            if( tab[ a ][ b ].nazwa == 'a' )
            {
                for( int c = 0; c < 4; c++ )
                {
                    for( int d = 0; d < 4; d++ )
                    {
                        if( tab[ a ][ b ].nazwa == 'a' ) // już sprawdziłeś nazwę wię się nie zmieni w paranormalny sposób w coś innego
                        {
                            wskaznik_na_element_kontenera = & tab[ a ][ b ].kontener1[ c ][ d ];
                        }
                        else // ten kod nigdy się nie wykona
                        {
                            wskaznik_na_element_kontenera = & tab[ a ][ b ].kontener2[ c ][ d ];
                        }
                        wskaznik_na_element_kontenera = funkcja_wewnetrzna( tab[ a ][ b ] );
                    }
                }
            }
            else if( tab[ a ][ b ].nazwa == 'b' )
            {
                //analogia do powyzszego...
            }
        }
    }
}

Nie zbyt długo myślałem nad tym co chcesz osiągnąć więc mój kod może być daleki od tego co chcesz osiągnąć.
P-145639
mateczek
» 2016-03-06 17:04:47
C/C++
double zmienna;
double * wskaznik;
wskaznik = & zmienna;
//   wskaznik = 3.14; // ten kod nie jest poprawny !!!! nie możesz do wskaźnika przypisać double !!!
( * wskaznik ) = 3.14; // tak jest porawnie
P-145643
motopompa
Temat założony przez niniejszego użytkownika
» 2016-03-06 23:50:15
Kaikso,
opisany przeze mnie przykład był faktycznie kiepski - problem jest bardziej złożony i chciałem go uprościć co zrobiłem beznadziejnie. W rzeczywistości jest więcej tablic klasy Klasa i więcej kontenerów, warunki na które zwróciłeś uwagę są także złożone, funkcje też. Chcąc uprościć problem uczyniłem kod bezsensownym :)

mateczek,
dzięki wielkie, to właśnie przeoczyłem i tu był pies pogrzebany:)

Ostatecznie obaj bardzo mi pomogliście, dzięki wielkie. Zamykając temat, moje podejście (poza zapomnianym (*wskaznik)... ) wygląda na dobre, tj. jest możliwość wykorzystania uniwersalnej funkcji do modyfikacji dowolnego elementu dowolnego kontenera znajdującego się w klasie przez wykorzystanie wskaźnika do pojedynczego elementu, który ma ona modyfikować.

Ostatecznie, co najważniejsze, po korekcie błędu zauważonego przez mateczek, dochodzimy do meritum, czyli:
C/C++
void funkcja_zewnetrzna( Klasa ** tab ) //do funkcji wrzucam jako argument całą tablicę obiektów klasy Klasa - w rzeczywistości i tak wszystkich potrzebuję, bo poprzez pętle modyfikuje im wszystkim wartości w kontenerach.
{
    double * wskaznik_na_element_kontenera; //definiujemy wskaznik
    wskaznik_na_element_kontenera = & tab[ licznik_1 ][ licznik_2 ].kontener1[ licznik_3 ][ licznik_4 ]; //ustawiamy wskaznik na adres tab[ licznik_1 ] [ licznik_2 ].kontener1[ licznik_3 ][ licznik_4 ], czyli na konkretny element kontenera kontener1 z obiektu nr [licznik_1][licznik_2] z tablicy obiektów klasy Klasa przesłanej w całości jako argument do funkcji.
    ( * wskaznik_na_element_kontenera ) = funkcja_wewnetrzna( tab[ licznik_1 ][ licznik_2 ] ); //wartość zwracana przez funkcje funkcja_wewnetrzna przepisuje do wskaźnika, czyli do adresu wskazywanego przez wskaźnik, modyfikując wartość przechowywaną we wskazanym elemencie kontenera
}

double funkcja_wewnetrzna( Klasa & obiekt_z_tab )
{
    double wynik;
    //wykonuje jakieś operacje liczbowe
    return( wynik );
}
Ostatecznie, podsumowując, kod:
C/C++
wskaznik_na_element_kontenera = & tab[ licznik_1 ][ licznik_2 ].kontener1[ licznik_3 ][ licznik_4 ];
( * wskaznik_na_element_kontenera ) = funkcja_wewnetrzna( tab[ licznik_1 ][ licznik_2 ] );
jest równoważny z
C/C++
tab[ licznik_1 ][ licznik_2 ].kontener1[ licznik_3 ][ licznik_4 ] = funkcja_wewnetrzna( tab[ licznik_1 ][ licznik_2 ] );
i o to chodziło :)
P-145653
« 1 »
  Strona 1 z 1