• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

question-closed C++ przypisanie obiektów typu dwóch różnych klas szablonowych

+1 głos
55 wizyt
pytanie zadane 17 czerwca w C i C++ przez dawid2002 Obywatel (1,840 p.)
zamknięte 17 czerwca przez dawid2002

Witam! Ostatnio czytając kurs C++ K.Kuczmarskiego autor tego kursu powiedział, że klasy szablonowe konkretyzowane innym zestawem parametrów są zupełnie odmiennymi typami. Zatem na przykładzie szablonu TStaticArray oraz jej obiektów a10Intow i a20Floatow przedstawił kod tego szablonu, który za pomocą przeciążonego operatora przypisania powoduje, że przypisanie tych odmiennych typów jest możliwe:

template <typename T, unsigned N> class TStaticArray
{
	T m_aTablica[N];

public:

	const unsigned ROZMIAR = N;

	T& operator[](unsigned uIndeks)
	{
	    return m_aTablica[uIndeks];
    }



    template <typename T2, unsigned N2>
    TStaticArray& operator=(const TStaticArray<T2, N2>& aTablica)
    {
        if (&aTablica != this)
        {
            if (N2 > N)
                cerr << "za duza tablica" << endl;

            for (unsigned i = 0; i < N2; ++i)
                (*this)[i] = aTablica[i];     	// (*this) – odwolanie do obiektu
        }
        return *this;
    }

};

Wszystko ładnie działa aż do momentu, gdy pojawi się zapis:

int main()
{
    TStaticArray<float,5> ob1;
    TStaticArray<int,4> ob2;

    ob1 = ob2;
     
     return 0;
}


Wtedy VS pokazuje błąd (dla instrukcji "&aTablica != this"):

"!=": brak konwersji z "TStaticArray<float,5> *" na "const TStaticArray<int,4> *"  

Oraz (dla: "(*this)[i] = aTablica[i];"):

dwuargumentowy "[": nie znaleziono żadnego operatora, który przyjmuje lewostronny operand typu "const TStaticArray<int,4>" (lub nie istnieje akceptowalna konwersja)

Zatem żeby rozwiązać problem zmieniłem w kodzie (zmiany są podświetlone):

template <typename T, unsigned N> class TStaticArray
{
public:

	T m_aTablica[N];      // Niestety musiałem uczynić go publicznym wskaźnikiem :(

	const unsigned ROZMIAR = N;

	T& operator[](unsigned uIndeks)
	{
	    return m_aTablica[uIndeks];
        }


    template <typename T2, unsigned N2>
    TStaticArray& operator=(const TStaticArray<T2, N2>& aTablica)
    {
        if ((void*)&aTablica != (void*)this)
        {
            if (N2 > N)
                cerr << "za duza tablica" << endl;

            for (unsigned i = 0; i < N2; ++i)
                (*this)[i] = aTablica.m_aTablica[i];
        }
        return *this;
    }

};

Mój problem polega na tym, że zmiany, które wprowadziłem w kodzie są niezbyt ładne (np: publiczny wskaźnik). W taki razie jak powinien wyglądać przyzwoity oraz działający kod?

Z góry bardzo dziękuje za pomoc!

EDIT:

Póki co udało mi się częściowo rozwiązać problem używając zaprzyjaźniania:

// (...)
template<typename,unsigned> friend class TStaticArray;

	T m_aTablica[N];

public:
// (...)

Aczkolwiek nadal muszę używać tej formy:

(*this)[i] = aTablica.m_aTablica[i];

Zamiast tej:

(*this)[i] = aTablica[i];

PS.

Proszę nie wincie mnie za to, że zadaje to pytanie, po prostu się uczę dopiero!

komentarz zamknięcia: znam już odpowiedź
komentarz 17 czerwca przez mokrowski VIP (107,640 p.)
Ok, ogólnie firend jest zły. Ale bardziej precyzyjnym pytaniem było by... co chcesz (dokładnie) osiągnąć? (bo masz jeszcze kilka błędów w kodzie)

1 odpowiedź

+1 głos
odpowiedź 17 czerwca przez adrian17 Mędrzec (187,480 p.)
wybrane 17 czerwca przez dawid2002
 
Najlepsza

"!=": brak konwersji z "TStaticArray<float,5> *" na "const TStaticArray<int,4> *"  

Chodzi o to porównanie:

if (&aTablica != this)

Jeśli typy są różne, to porównanie nie jest możliwe (nawet gdyby było, to byłoby zawsze false). Jeśli są równe, to ma sens. Może zrób osobne przeładowanie dla tego samego typu?

dwuargumentowy "[": nie znaleziono żadnego operatora, który przyjmuje lewostronny operand typu "const TStaticArray<int,4>" (lub nie istnieje akceptowalna konwersja)

To wygląda na prosty problem z const correctness. Zrób dwa przeładowania operatora[]:

    T& operator[](unsigned uIndeks)
    {
        return m_aTablica[uIndeks];
    }
    const T& operator[](unsigned uIndeks) const
    {
        return m_aTablica[uIndeks];
    }

 

komentarz 17 czerwca przez dawid2002 Obywatel (1,840 p.)

Wielkie dzięki! yes

Ja jeszcze dodatkowo napisałem przeładowanie dla operatora !=

template<typename Type,unsigned NN> bool operator!=(const TStaticArray<Type,NN> ob)
{
     return (static_cast<void*>(this) != &ob);
}

if(*this != aTablica)    // pięknie działa :) 

 

Podobne pytania

0 głosów
2 odpowiedzi 80 wizyt
0 głosów
2 odpowiedzi 77 wizyt
+2 głosów
1 odpowiedź 205 wizyt
pytanie zadane 30 stycznia 2018 w C# i .NET przez Błażej Gonczar Obywatel (1,630 p.)
Porady nie od parady
Publikując kody źródłowe korzystaj ze specjalnego bloczku koloryzującego składnię (przycisk z napisem code w edytorze). Nie zapomnij o ustawieniu odpowiedniego języka z rozwijanego menu oraz czytelnym formatowaniu kodu.Przycisk code

64,843 zapytań

111,309 odpowiedzi

234,099 komentarzy

46,710 pasjonatów

Przeglądających: 238
Pasjonatów: 8 Gości: 230

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto dwie polecane książki warte uwagi. Pełną listę znajdziesz tutaj.

...