CYFROWY BARON • PROGRAMOWANIE • Zobacz wątek - Przeciążenie operatora indeksowania (dwa wymiary)

Przeciążenie operatora indeksowania (dwa wymiary)

dział ogólny

Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez lidamian » wtorek, 15 lutego 2011, 18:27

Jak przeciążyć operator dla jednego wymiaru to wiem, ale dla dwóch?

To nie działa:
KOD cpp:     UKRYJ  
class ctest
{
private:
        int plansza[5][5];
public:
        int operator [] (int x, int y); // Tak nie działa
        int operator [][] (int x, int y); // Tak nie działa
} test;
...
int x = test[2][2]; // Tak chcę się odwoływać do pola planszy
 


Zna się ktoś?
Avatar użytkownika
lidamian
Bladawiec
Bladawiec
 
Posty: 29
Dołączył(a): piątek, 19 września 2008, 15:25
Podziękował : 4
Otrzymał podziękowań: 0
    Windows 7Firefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez polymorphism » wtorek, 15 lutego 2011, 19:48

Zna się.

operator[][] nie daje się przeładować, bo taki w C++ nie istnieje. Istnieje tylko pojedynczy operator indeksowania.

Możesz zrobić tak:
KOD cpp:     UKRYJ  
int* operator [] (int x) { return &plansza[x][0]; }
const int* operator [] (int x)const { return &plansza[x][0]; }
C++ Reference - opis wszystkich klas STL-a i funkcji C.

Za ten post autor polymorphism otrzymał podziękowanie od:
lidamian
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez lidamian » wtorek, 15 lutego 2011, 20:52

O stary! o0

Składam pokłon, to jest genialne ;D W międzyczasie szukałem innych rozwiązań i trafiłem na używanie klasy pomocniczej co zaciemniało kod i było "wolne". Oczywiście przestudiowałem Twój kod i doszedłem do wniosku, że jest to programistyczny trick polegający na oszukaniu kompilatora. Od siebie dodam, że drugie przeciążenie może wyglądać tak:

KOD cpp:     UKRYJ  
struct
{
        int plansza[5][5];

        int* operator [] (int x) { return &plansza[x][0]; }
        void operator [] (int) const { }
} test;

void main()
{
        test[1][2] = 12;
        test[4][3] = 43;
        test[1][0] = 10;
        printf("x: %i\n\n", test[1][2]);

        for(int y=0; y < 5; y++)
        {
                for(int x=0; x < 5; x++) printf("%i\t", test[x][y]);
                printf("\n");
        }
        getch();
}


Oczywiście pierwsze co przyszło mi na myśl to: "Jak to wykorzystać do przeciążenia trzeciego operatora indeksowania?"

Jeszcze raz wielkie dzięki ;)
Pozdrawiam
Avatar użytkownika
lidamian
Bladawiec
Bladawiec
 
Posty: 29
Dołączył(a): piątek, 19 września 2008, 15:25
Podziękował : 4
Otrzymał podziękowań: 0
    Windows 7Firefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez polymorphism » wtorek, 15 lutego 2011, 21:36

(...) że jest to programistyczny trick polegający na oszukaniu kompilatora.

Żadnego oszustwa tu nie ma, ten kod jest jak najbardziej poprawny składniowo.

W międzyczasie szukałem innych rozwiązań i trafiłem na używanie klasy pomocniczej co zaciemniało kod i było "wolne".

Na początku chciałem dać kod z klasą pomocniczą, ale... nie chciało mi się go pisać ;) I takie rozwiązanie wcale nie musi być wolne. W wersji release kompilator w procesie optymalizacji może rozwinąć metody, co w konsekwencji da kod równie wydajny co wersja na wskaźnikach. Dodatkowo kod z taką klasą daje Ci większą kontrolę nad dostępem do poszczególnych elementów tablicy.

Jak to wykorzystać do przeciążenia trzeciego operatora indeksowania?

Bez klasy pomocniczej się nie obędzie.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez Cyfrowy Baron » środa, 16 lutego 2011, 09:41

lidmian napisał(a):(...) że jest to programistyczny trick polegający na oszukaniu kompilatora.


:x To dobre! Jak oszukać komputer by zrobił coś do czego nie został zaprogramowany??? Chciałbym coś takiego zobaczyć? To prawie tak jakby obdarzyć komputer świadomością.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez polymorphism » środa, 16 lutego 2011, 11:02

Jak oszukać komputer by zrobił coś do czego nie został zaprogramowany???

Nie komputer, tylko kompilator ;) Jeśli chodzi o oszukiwanie, to można powiedzieć, że przy implementowaniu delegatów wszelkie rzutowania wskaźników na metody to w pewnym sensie oszukiwanie kompilatora. Bardziej obrazowy przykład to stworzenie wątku funkcją CreateThread, którego entry-pointem jest niestatyczna metoda jakiejś klasy.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez Cyfrowy Baron » środa, 16 lutego 2011, 11:15

To nie jest żadne oszukiwanie kompilatora, gdyż odbywa się w ramach dopuszczanych przez dany język programowania i jest zaprogramowane przez programistę. Program nie wykona operacji do której nie został zaprogramowany, a kompilator nie skompiluje kodu niezgodnego z językiem programowania.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez polymorphism » środa, 16 lutego 2011, 11:45

(...) a kompilator nie skompiluje kodu niezgodnego z językiem programowania.

No właśnie na tym polega to całe oszustwo. Żeby coś, co jest niezgodne ze składnią języka - w tym przypadku przypisanie wskaźnika na metodę wskaźnikowi na funkcję - doprowadzić do postaci, która będzie zgodna składniowo. Choć oczywiście warto pamiętać, że ta poprawność składniowa nie gwarantuje poprawności działania czy też przenośności. To jest jazda po bandzie, która wymaga znajomości tego, co się dzieje pod maską języka C++.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez Cyfrowy Baron » środa, 16 lutego 2011, 12:56

To mnie nie przekonuje. Jeżeli kompilator kompiluje kod, to dlatego, że jest on zgodny ze składnią danego języka. Gdyby sytuacja o której piszesz, czyli - coś jest zgodne składniowo, ale nie jest zgodne z językiem programowania - zadziałało to powiedziałbym, że faktycznie kompilator dał się oszukać. By jednak kod działał, a nie tylko wyglądał tak jakby miał działać, to musi być zgodny ze składnią języka. Sam często spotkam się z sytuacją w której przypisanie wskaźnika pozwala skompilować kod mimo iż taki kod już na pierwszy rzut oka jest pozbawiony logiki, jednak nie zdarzyło mi się by to zadziałało. Najczęściej przy próbie użycia program wyrzuca błędy, rzadziej nic się nie dzieje, czyli program nie wykonuje operacji. Nie nazwałbym jednak takiej sytuacji oszustwem lecz błędem.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez polymorphism » środa, 16 lutego 2011, 13:59

Gdyby sytuacja o której piszesz, czyli - coś jest zgodne składniowo, ale nie jest zgodne z językiem programowania - zadziałało to powiedziałbym, że faktycznie kompilator dał się oszukać.

Dałem przykład z CreateThread. Da się tak oszukać kompilator, żeby entry-pointem wątku była metoda wywołana na rzecz jakiegoś obiektu. I to jest kod, który poza tym, że wygląda, także działa. Przykład:
KOD cpp:     UKRYJ  
class foo
{
private:

        DWORD WINAPI thread_proc()
        {
                cout << "wywolanie foo::thread_proc na rzecz obiektu this = " << this << "\n";

                Sleep(3000);
                return 0;
        }
public:

        foo()
        {
                DWORD id;
                DWORD (WINAPI foo::*mem_ptr)() = &foo::thread_proc;

                HANDLE h = CreateThread(NULL,
                                        0,
                                        *((LPTHREAD_START_ROUTINE*)((void*)&mem_ptr)),
                                        this,
                                        0,
                                        &id);

                WaitForSingleObject(h, INFINITE);
                CloseHandle(h);
        }
};

...
foo o1;
foo o2;
foo o3;

 

Dla kogoś, kto wie, jak "działa" C++, sprawa jest prosta. Ale dla kogoś, kto nie wie, to niezbyt jasna sprawa, i ogólnie WTF?!

Ten kod działa na VC i MinGW.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez Cyfrowy Baron » środa, 16 lutego 2011, 15:55

Twój kod nie wykracza jednak poza ramy języka programowania, lecz wykorzystuje jego luki. Kod działa i robi to do czego został zaprogramowany ponieważ nie zawiera błędu składni. Stwórz kod zawierający błąd składniowy a mimo to dający się skompilować, wtedy uznam, że kompilator został oszukany.

Oszukać można tylko osobę mającą świadomość i przekonaną, że ma do czynienia z prawdziwym obrazem rzeczywistości, podczas gdy wytworzony został obraz fałszywy. To nie ma miejsca w przypadku kompilatora, gdyż nie posiada TO świadomości.
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez polymorphism » środa, 16 lutego 2011, 16:45

Twój kod nie wykracza jednak poza ramy języka programowania, lecz wykorzystuje jego luki.

No, tak. Dzięki tym lukom mogę robić rzeczy, które nie do końca są poprawne... koncepcyjnie.

Stwórz kod zawierający błąd składniowy a mimo to dający się skompilować, wtedy uznam, że kompilator został oszukany.

Parafrazując Ciebie: wykorzystałbym wtedy lukę kompilatora - też źle ;) Zresztą nie widzę powodu, dla którego miałbym szukać takich błędów. Nie o to tu przecież chodzi...

Oszukać można tylko osobę mającą świadomość i przekonaną, że ma do czynienia z prawdziwym obrazem rzeczywistości, podczas gdy wytworzony został obraz fałszywy. To nie ma miejsca w przypadku kompilatora, gdyż nie posiada TO świadomości.

:x A słyszałeś o czymś takim jak skrót myślowy?

Zwrot 'oszukać kompilator' znaczy mniej więcej tyle, co stworzyć taką konstrukcję, taki kod, który umożliwi mi wykonanie czegoś, na co nie pozwalają reguły języka, zachowując przy tym zgodność składniową. Chyba jaśniej się nie da tego wytłumaczyć.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez lzommer » czwartek, 7 lutego 2013, 15:53

Mozna i tak, topornie ale jest mozliwosc kontroli indeksow tablicy.

KOD cpp:     UKRYJ  
class H
{
private:
        double g[3][3];
        int i;
public:
        H(int x)
        {
                i=x;
        }
        double operator[](int j)
        {
                return g[i][j];
        }
};

class M
{
        int i;
public:
        H  operator[]( int i)
        {
                H       z=  H(i);
                return z;
        }
} ;
Ostatnio edytowano czwartek, 7 lutego 2013, 16:03 przez polymorphism, łącznie edytowano 1 raz
Powód: Kod wstawiaj w znaczniki CPP!
Avatar użytkownika
lzommer
Bladawiec
Bladawiec
 
Posty: 14
Dołączył(a): piątek, 19 października 2012, 10:01
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: winXP
Kompilator: C++ Builder
Gadu Gadu: 0
    Windows XPInternet Explorer 8

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez polymorphism » czwartek, 7 lutego 2013, 16:15

Klasa M bez sensu. Za każdym razem, gdy wywołujesz jej operator [], tworzysz nową tablicę (obiekt klasy H), którą zwracasz przez wartość.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    Windows XPFirefox

Re: Przeciążenie operatora indeksowania (dwa wymiary)

Nowy postprzez lzommer » czwartek, 7 lutego 2013, 20:41

No to zrobmy inaczej:
KOD cpp:     UKRYJ  
#include <conio.h>
#include <iostream>

using namespace std;

class M;

        class hlp
               {

                 M & m;
                 int x;
         public:
                 hlp(M & _m, int _x):m(_m),x(_x) {};
                 double & operator [] (int y);
        };

class M
{
                 double g[3][3];
 public:
                 M()
                 { // dla przykladu, niech tablica g:
                         for(int i=0; i<3; i++)
                                 for(int j=0; j<3; j++)
                                         g[i][j]=i+(double)j/10.;
                 };
                 hlp operator [] (int x)
                 {
                                return hlp(*this, x);
                 }
                 double& operator()(int & x, const int & y)
                 {
                                // BadBouns(x,y); // tutaj latwa kontrola indeksow.
                                return g[x][y];
                 }
};

        double & hlp::operator [] (int  y)
        {
                 return m(x,y);
        }


main()
{
// Sprawdzmy:
        M m;
        // np:
        cout << m.operator[](1).operator[](2) << endl;
        // lub
        for(int i=0; i<3; i++)
        {
                for(int j=0; j<3; j++)
                        cout << m[i][j] << "  ";
                cout<< endl;
        }

        getch();
 }
Ostatnio edytowano piątek, 8 lutego 2013, 11:02 przez lzommer, łącznie edytowano 1 raz
Avatar użytkownika
lzommer
Bladawiec
Bladawiec
 
Posty: 14
Dołączył(a): piątek, 19 października 2012, 10:01
Podziękował : 11
Otrzymał podziękowań: 0
System operacyjny: winXP
Kompilator: C++ Builder
Gadu Gadu: 0
    Windows 7Internet Explorer 9

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 7 gości

cron