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

Zwracanie dynamicznej tablicy 2d. Jak to odebrać?

Ostatnio zmodyfikowano 2013-07-01 18:26
Autor Wiadomość
johny
Temat założony przez niniejszego użytkownika
Zwracanie dynamicznej tablicy 2d. Jak to odebrać?
» 2013-07-01 01:26:59
Pomoże mi ktoś w ustaleniu w jaki sposób odebrać dynamiczną macierz 2d, która jest zwracana przez metodę klasy ImgInMat? Klasa ImgInMat ma zapisywać obrazek w macierzy.
C/C++
//plik ImgInMat.h
#include <SFML/Graphics.hpp>
template < typename T >
class ImgInMat {
    size_t _rows, _cols;
public:
    //T **tab;
    ImgInMat() { };
    T ** ImgToMat( const sf::Image & obr );
};

C/C++
//plik ImgInMat.cpp
#include "ImgInMat.h"
#include <iostream>

template < typename T > T ** ImgInMat < T >::ImgToMat( const sf::Image & obr )
{
    _rows = obr.GetHeight();
    _cols = obr.GetWidth();
    //tab=new T*[_rows];
    T ** tab = new T *[ _rows ];
    for( int i = 0; i < _rows; i++ )
         tab[ i ] = new T[ _cols ];
   
    for( int j = 0; j < _rows; j++ )
    for( int i = 0; i < _cols; i++ )
         tab[ j ][ i ] = obr.GetPixel( i, j ).r;
   
    return tab;
}

C/C++
//fragment maina
ImgInMat < int > macierz;
int ** a = macierz.ImgToMat( obrazek );

obj/Debug/main.o||In function `main':|
/home/mateusz/CodeBlocks/30_06/Pro1/main.cpp|36|undefined reference to `ImgInMat<int>::ImgToMat(sf::Image const&)'|
||=== Build finished: 1 errors, 0 warnings (0 minutes, 0 seconds) ===|
Błąd wywala w 36 (czyli drugiej widocznej tutaj we fragmencie) linijce pliku main.cpp
P-86688
unimator
» 2013-07-01 11:09:22
Błąd oznacza, że nie masz definicji (ciała) funkcji ImgInMat<int>::ImgToMat(sf::Image const&). Sprawdź czy na pewno linkujesz plik ImgInMat.cpp.
P-86701
Monika90
» 2013-07-01 11:15:05
To jest szablon, więc definicja funkcji musi być w pliku ImgInMat.h, (no chyba, że chesz używać explicit instantiation).
P-86702
johny
Temat założony przez niniejszego użytkownika
» 2013-07-01 17:40:08
@unimator, plik ImgInMat.cpp był linkowany.

@Monika90, rzeczywiście po przeniesieniu definicji do ImgInMat.h wszystko pięknie działa.

Mam jeszcze pytanie co do explicit instantiation. Zaletą i sensem stosowania szablonów jest pewne uogólnienie, dzięki któremu nie trzeba tej samej klasy definiować kilka razy, dla każdego typu z osobna. Kompilator podczas kompilacji dokonuje konkretyzacji szablonu "w locie" (tzn generuje właściwy kod klasy, tylko wtedy, gdy szablon zostanie 'wywołany' dla konkretnego typu). Tak ja to rozumiem. Explicit instantiation jest (z tego co się dowiedziałem [chyba, że źle się dowiedziałem]) jawną konkretyzacją szablonu. Postanowiłem sprawdzić, czy to zadziała. I poniższy kod działa rzeczywiście.
C/C++
//plik .h
#include <SFML/Graphics.hpp>
template < typename T >
class ImgInMat {
    size_t _rows, _cols;
public:
    //T **tab;
    ImgInMat() { };
    //T **ImgToMat(const sf::Image &obr);
    int ** ImgToMat( const sf::Image & obr );
};
C/C++
#include "ImgInMat.h"

template <> int ** ImgInMat < int >::ImgToMat( const sf::Image & obr )
{
    _rows = obr.GetHeight();
    _cols = obr.GetWidth();
    //tab=new T*[_rows];
    int ** tab = new int *[ _rows ];
    for( int i = 0; i < _rows; i++ )
         tab[ i ] = new int[ _cols ];
   
    for( int j = 0; j < _rows; j++ )
    for( int i = 0; i < _cols; i++ )
         tab[ j ][ i ] = obr.GetPixel( i, j ).r;
   
    return tab;
}
C/C++
//main- fragment
ImgInMat < int > macierz;
int ** a = macierz.ImgToMat( obrazek );
std::cout << a[ 1 ][ 1 ];

Tylko teraz nasuwa się pytanie, jaki jest sens stosowania jawnej konkretyzacji, skoro zabija ona całą funkcjonalność, którą wprowadzają szablony? Nie rozumiem tego. Niech mi ktoś wytłumaczy, ale tak jak krowie na granicy :D
P-86738
pekfos
» 2013-07-01 17:45:51
To, co zrobiłeś, to specjalizacja szablonu, a nie explicit instantiation.
P-86739
johny
Temat założony przez niniejszego użytkownika
» 2013-07-01 18:26:36
@pekfos, racja. No więc z tego co teraz udało mi się wyczytać to explicit instantiation jest realizowane przez dołączenie "template class ImgInMat<int>;" na końcu pliku cpp. Dzięki temu tworzymy konkretyzacje, jeszcze przed użyciem klasy/funkcji w kodzie. Tak?
Czy coś jeszcze warto o tym wiedzieć?

C/C++
#include "ImgInMat.h"
#include <iostream>

template < typename T > T ** ImgInMat < T >::ImgToMat( const sf::Image & obr )
{
    _rows = obr.GetHeight();
    _cols = obr.GetWidth();
    //tab=new T*[_rows];
    T ** tab = new T *[ _rows ];
    for( int i = 0; i < _rows; i++ )
         tab[ i ] = new T[ _cols ];
   
    for( int j = 0; j < _rows; j++ )
    for( int i = 0; i < _cols; i++ )
         tab[ j ][ i ] = obr.GetPixel( i, j ).r;
   
    return tab;
}

template class ImgInMat < int >;
template class ImgInMat < float >;
template class ImgInMat < double >;
W dalszym ciągu, czy jest sens używania specjalizacji szablonu? To tak jak deklarowanie przeciążonej funkcji/metody. Na moje oko niczym się nie różni.
P-86746
« 1 »
  Strona 1 z 1