5

Hej, pojawia się błąd łącznika LNK2019: nierozwiązany symbol zewnętrzny podczas próby użycia przeciążonego operatora +. Pokażę ci wycinek z klasy i sposób, w jaki go używam. Jeśli chcesz zobaczyć więcej, daj mi znać, po prostu postaram się zachować zwięzłość.Przeciążanie + operator z szablonami

/** vec.h **/ 
#ifndef __VEC_H_ 
#define __VEC_H_ 

#include <iostream> 
#include <vector> 

namespace xoor{ 

    template<typename T> 
    class vec{ 

    public: 
     inline friend vec<T> operator + (const vec<T>&, const vec<T>&); 
     inline const vec<T>& operator += (const vec<T>&); 

    private: 
     std::vector<T> m_index; 
    }; // Vec. 


    template<typename T> 
    vec<T>& operator + (const vec<T>& a, const vec<T>& b){ 
     vec<T> product = a; 
     product += b; 

     return product; 
    } // Addition. 

    template<typename T> 
    const vec<T>& vec<T>::operator += (const vec<T>& v){ 
     for (unsigned short i =0; i < m_index.size(); ++i){ 
      if (i >= v.size()) 
       break; 
      m_index[i] += v.getIndex()[i]; 
     } 

     return * this; 
    } // Addition Compound. 


} // xoor 

#endif // __VEC_H_ 

Zwróć uwagę, że mam również [] przeciążone, dlatego właśnie uzyskuję dostęp do części m_indexu. getIndex() po prostu zwraca m_index. I wielkość() zwraca m_index.size()

/** main.cpp **/ 

#include <iostream> 
#include "vec.h" 

void testHook(); 

int main(){ 
    testHook(); 
    system("PAUSE"); 
    return 0; 
} 

void testHook(){ 
    using namespace xoor; 
    vec<double> vA(3); // passing 3 for 3 elements 
    vec<double> vB(3); 

    // v + v 
    std::cout << "\n\tA + B = "; 
    vec<double> vAB(3); 
    vAB = vA + vB; // PRODUCES THE LNK2019 
    vAB.print(std::cout); // Outputs the vec class to the console. 
} 

komunikat o błędzie:

Error 1 error LNK2019: unresolved external symbol "class xoor::vec<double> __cdecl xoor::operator+(class xoor::vec<double> const &,class xoor::vec<double> const &)" ([email protected]@[email protected]@[email protected]@[email protected]) referenced in function "void __cdecl testHook(void)" ([email protected]@YAXXZ) main.obj 

Aktualizacja:

Poniżej znajduje się bezpośrednio powyżej definicji klasy. Wciąż mam ten sam błąd linkera, jak opisano powyżej.

template<typename T> 
    class vec; 

    template<typename T> 
    vec<T> operator + (const vec<T>&, const vec<T>&); 

Aktualizacja 2: Rozwiązanie.

Powyższa aktualizacja jest niepoprawna. Rozwiązanie sbi działało, po prostu nie udało mi się dopasować operatora w następujący sposób.

template<typename T> 
    vec<T> operator +<T> (const vec<T>&, const vec<T>&); 

sbi i David zastanawiali się, dlaczego używam przyjaciół w pierwszej kolejności. Początkowo używałem ich, ponieważ nie można przekazać dwóch parametrów do przeciążonego operatora binarnego, takiego jak +, i natychmiast poszukiwano przyjaciół jako rozwiązania. Jak się okazuje, nadal można z łatwością używać operatora binarnego za pomocą jednego parametru. Oto ostateczne rozwiązanie.

// ... 
template<typename T> 
class vec{ 
    public: 
    const vec<T> operator + (const vec<T>&, const vec<T>&)const; 
    // ... 

}; // Vec. 

template<typename T> 
const vec<T> vec<T>::operator + (const vec<T>& v)const{ 
    matrix<T> product = *this; 
    vec(product += v); 
} // Addition. 

Ponadto, dla każdego, kto to czyta, warto sprawdzić jego notatki na dole odpowiedzi. Są pewne rzeczy, które robiłem, które są zbędne.

Dzięki za pomoc dla wszystkich. Szczęśliwe kodowanie.

+0

Jeśli to zadanie domowe (i wygląda podejrzanie), dodaj tag 'homework'. Wielu z nas odmawia odpowiedzi na zadania domowe w inny sposób, dzięki czemu uczysz się z nich jak najwięcej (podczas gdy inne pytania są zwykle zadawane, aby każdy, kto pyta, mógł robić to, co robi tak szybko, jak to możliwe). – sbi

Odpowiedz

7

Aby zaprzyjaźnić się szablon, myślę, że trzeba zadeklarować tego szablonu przed definicja klasy, w której chcesz się zaprzyjaźnić. Jednakże, aby ta deklaracja została skompilowana, musisz przekazać dalej - zadeklaruj szablon klasy. Tak to powinno działać:

template<typename T> 
class vec; 

template<typename T> 
vec<T> operator + (vec<T>, const vec<T>&); 

template<typename T> 
class vec{ 
public: 
    friend vec<T> operator +<T> (vec<T>, const vec<T>&); 
// ... 

Ten zaprzyjaźnia konkretną instancję szablonu operator+() funkcję, a mianowicie operator+<T>. (Możesz też zaprzyjaźnić się ze wszystkimi wystąpieniami szablonu:

// no forward declarations necessary 

template<typename T> 
class some_class { 
    template<typename U> 
    friend void f(vec<U>&); 
    // ... 
}; 

Jest to jednak mniej przydatne niż inne.)

Edit: Komentarz przez Dawida dało mi do myślenia (powinno zrobiłem to od początku) i które prowadzą do odkrycia, że ​​deklaracja friend jest niepotrzebna!. Twój operator+ używa tylko jednej funkcji składowej public z vec (operator+=) i dlatego nie musi być klasą friend. Więc powyższe byłoby uprościć do

template<typename T> 
class vec{ 
public: 
    // ... 
}; 

template<typename T> 
vec<T> operator + (vec<T> a, const vec<T>& b){ 
    a += b; 
    return a; 
} 

Oto jeszcze kilka uwag:

  • operator+() (które ładnie realizowane na szczycie operator+=(), BTW) powinny brać swój lewy argument za kopii.
  • nie Czy deklarują funkcje inline, określić je tak.
  • Otrzymano operator+=() zwracając odwołanie inne niż const, ponieważ każdy oczekuje, że f(m1+=m2) zadziała, nawet jeśli f() przyjmuje swój argument jako odniesienie inne niż const.
  • Wewnątrz szablonu klasy, w większości miejsc można pominąć listę parametrów szablonu, odwołując się do klasy. Możesz więc powiedzieć: vec& operator += (const vec&);. (Nie można zrobić poza szablonem, choć - na przykład przy definiowaniu tego przedsiębiorcę poza klasą.)
  • std::vector „s typ indeksu orkisz std::vector<blah>::size_type, nieunsigned short.
+0

Dzięki za odpowiedź i próbkę. Niestety to nie zadziałało. Będę próbował kilka rzeczy. Jeśli coś wymyślisz, sprawdzę to regularnie. – Xoorath

+0

@Xoathath: "To nie działa" jest zbyt ogólnikowe, aby móc cokolwiek powiedzieć. (W rzeczywistości mam tutaj wersję, która kompiluje i łączy się z VC, więc wiem, że to działa w zasadzie.) – sbi

+0

Przepraszam, kolego. Sekunda. Zaktualizuję fragment kodu. – Xoorath

7

Typ zwracany tutaj:

inline friend vec<T> operator + (const vec<T>&, const vec<T>&); 

nie pasuje tutaj:

template<typename T> 
    vec<T>& operator + (const vec<T>& a, const vec<T>& b){ 
     vec<T> product = a; 
     product += b; 

     return product; 
    } // Addition. 
+0

Ponadto, nie jest to funkcja __declarations__, która musi być oznaczona jako 'inline', ale funkcja __definitions__. Więc to 'przyjaciel VEC operator + (const vec &, const vec &);' i 'const vec & operator + = (const vec &);', ale 'inline vec operator + (const vec &, const vec &) {...} 'i' inline const vec & operator + = (const vec &) {...} '. Och, i jakie są powody, dla których '+ =' zwraca 'const vec &'? Myślę, że powinno to być odniesienie inne niż 'const". – sbi

+1

Jeszcze jedna rzecz (naprawdę, powinienem był sam odpowiedzieć ...): Ponieważ operandy po lewej stronie operandu zostaną skopiowane od razu, argument ten powinien zostać przekazany za pomocą kopii zamiast odwołania "const". To było kiedyś postrzegane inaczej (kopiowanie jest szczegółem implementacji i nie powinno przeciekać do interfejsu), ale mądrzy ludzie odkryli, że zrobienie kopii po przekazaniu argumentu daje kompilatorom jeszcze kilka możliwości optymalizacji (takich jak pominięcie kopiowania, gdy operand jest tymczasowy, który i tak zostanie zniszczony). – sbi

+0

Dziękuję bardzo, proszę pana. – Xoorath

Powiązane problemy