Zwracanie dynamicznej tablicy 2d. Jak to odebrać?
Ostatnio zmodyfikowano 2013-07-01 18:26
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. #include <SFML/Graphics.hpp> template < typename T > class ImgInMat { size_t _rows, _cols; public: ImgInMat() { }; T ** ImgToMat( const sf::Image & obr ); };
#include "ImgInMat.h" #include <iostream>
template < typename T > T ** ImgInMat < T >::ImgToMat( const sf::Image & obr ) { _rows = obr.GetHeight(); _cols = obr.GetWidth(); 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; }
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 |
|
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. |
|
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). |
|
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. #include <SFML/Graphics.hpp> template < typename T > class ImgInMat { size_t _rows, _cols; public: ImgInMat() { }; int ** ImgToMat( const sf::Image & obr ); };
#include "ImgInMat.h"
template <> int ** ImgInMat < int >::ImgToMat( const sf::Image & obr ) { _rows = obr.GetHeight(); _cols = obr.GetWidth(); 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; }
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 |
|
pekfos |
» 2013-07-01 17:45:51 To, co zrobiłeś, to specjalizacja szablonu, a nie explicit instantiation. |
|
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ć? #include "ImgInMat.h" #include <iostream>
template < typename T > T ** ImgInMat < T >::ImgToMat( const sf::Image & obr ) { _rows = obr.GetHeight(); _cols = obr.GetWidth(); 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. |
|
« 1 » |