Operator overloading and inheritance with template classes.

Discussion in 'C++' started by shabbir, May 10, 2007.

  1. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    Just thought of having a simple example which has everything you need to know about the basics of C++. It has Inheritance, polymorphism, operator overloading, templates using friend as well as non-friend functions.
    Code:
    #include <iostream>
    using namespace std;
    
    template <typename T>
    class Base
    {
    	protected:
    		T strQuery;
    	public:
    		Base(T q = NULL): strQuery(q){}
    		Base(Base<T> &b): strQuery(b.strQuery){}
    		~Base(){}
    
    		T getQuery(void){return strQuery;}
    		void setQuery(T q){strQuery = q;}		
    };
    
    template <typename T>
    class Derived : public Base<T>
    {
    	public:
    		//Default Functions also provided
    		Derived(const T q = NULL): Base<T>(q){}
    		Derived(const Derived &d): Base<T>(d.strQuery){}
    		~Derived(){}
    		Derived<T> operator=(const Derived<T> d)
    		{
    			if(this != &d)
    				this->strQuery=d.strQuery;
    			return *this;
    		}
    		
    		//Input Output Functions 
    		friend ostream& operator <<(ostream&,const Derived<T>&);
    		friend istream& operator >>(istream&,Derived<T>&);
    
    		//op + Functionality
    		Derived<T> operator + (const Derived<T>) const;
    		Derived<T> operator + (const T) const;
    		friend Derived<T> operator + (const T,const Derived<T>);
    		Derived<T>& operator ++ ();
    		Derived<T>& operator ++ (int);
    		Derived<T>& operator += (const Derived<T>);
    };
    
    template<typename T>
    ostream& operator <<(ostream& out,const Derived<T>& d)
    {
    	out<<d.strQuery;
    	return out;
    }
    
    template<typename T>
    istream& operator >>(istream& in,Derived<T>& d)
    {
    	in>>d.strQuery;
    	return in;
    }
    
    template<typename T>
    Derived<T> Derived<T>::operator + (const Derived<T> d) const
    {
    	Derived<T> temp;
    	temp.strQuery = this->strQuery + d.strQuery;
    	return temp;	
    }
     
    template<typename T>
    Derived<T> Derived<T>::operator + (const T t) const
    {
    	Derived<T> temp;
    	temp.strQuery = this->strQuery + t;
    	return temp;
    }
    
    template<typename T>
    Derived<T> operator + (const T t,const Derived<T> d)
    {
    	Derived<T> temp;
    	temp.strQuery = d.strQuery + t;
    	return temp;
    }
    
    template<typename T>
    Derived<T>& Derived<T>::operator ++ ()
    {
    	++(this->strQuery);
    	return *this;
    }
    
    template<typename T>
    Derived<T>& Derived<T>::operator ++ (int)
    {
    	this->strQuery++;
    	return *this;
    }
    
    template<typename T>
    Derived<T>& Derived<T>::operator += (const Derived<T> d)
    {
    	this->strQuery += d.strQuery;
    	return *this;
    }
    
    int main(int argc,char *argv[])
    {
    	Derived<double> d1,d2(10);
    	Derived<double> d3(d1);
    	cout<<"Enter Number\n";
    	cin>>d1;
    	cout<<d1;
    	cout<<endl;
    	d2=d1;
    	
    	d3 = d1 + 1;
    	d3 = d2++;
    	d3=++d2;
    	d3 = d2 = d1 = 1.2L;
    	d3 += d2;
    	cout<<d3<<"\t"<<d2<<"\t"<<d1<<"\n";
    	return 0;
    }
     
    WRaiTH and huckberry like this.
  2. jijojs

    jijojs New Member

    Joined:
    Jun 14, 2007
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    Hi ,
    I pasted the code given and when i am executing this it is not working .I am using a gcc 4.1.2
    The error showed by the compller is

    In file included from /usr/include/c++/4.1.2/backward/iostream.h:31,
    from netoprinhtem.cpp:1:
    /usr/include/c++/4.1.2/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
    netoprinhtem.cpp:33: warning: friend declaration ‘std::eek:stream& operator<<(std::eek:stream&, const Derived<T>&)’ declares a non-template function
    netoprinhtem.cpp:33: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
    netoprinhtem.cpp:34: warning: friend declaration ‘std::istream& operator>>(std::istream&, Derived<T>&)’ declares a non-template function
    netoprinhtem.cpp:39: warning: friend declaration ‘Derived<T> operator+(T, Derived<T>)’ declares a non-template function
    netoprinhtem.cpp: In function ‘int main(int, char**)’:
    netoprinhtem.cpp:106: warning: converting to non-pointer type ‘double’ from NULL
    netoprinhtem.cpp: In member function ‘Derived<T> Derived<T>::eek:perator+(T) const [with T = double]’:
    netoprinhtem.cpp:114: instantiated from here
    netoprinhtem.cpp:70: warning: converting to non-pointer type ‘double’ from NULL
    /tmp/ccFkepAp.o: In function `main':
    netoprinhtem.cpp:(.text+0xe5): undefined reference to `operator>>(std::basic_istream<char, std::char_traits<char> >&, Derived<double>&)'
    netoprinhtem.cpp:(.text+0xf8): undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Derived<double> const&)'
    netoprinhtem.cpp:(.text+0x41c): undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Derived<double> const&)'
    netoprinhtem.cpp:(.text+0x43d): undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Derived<double> const&)'
    netoprinhtem.cpp:(.text+0x45e): undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Derived<double> const&)'
    collect2: ld returned 1 exit status

    Please help me about this .Whenever i am using operator everloading in template class i am getting problems..
     
  3. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    You should replace
    Code:
    #include<iostream.h>
    with
    Code:
    #include <iostream>
    using namespace std;
     
  4. jijojs

    jijojs New Member

    Joined:
    Jun 14, 2007
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    Sir,
    Thanks for replying to my post.
    But after replacing also the compliler shows errors. The error generate by the compiler is
    netoprinhtem.cpp:34: warning: friend declaration ‘std::eek:stream& operator<<(std::eek:stream&, const Derived<T>&)’ declares a non-template function
    netoprinhtem.cpp:34: warning: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here) -Wno-non-template-friend disables this warning
    netoprinhtem.cpp:35: warning: friend declaration ‘std::istream& operator>>(std::istream&, Derived<T>&)’ declares a non-template function
    netoprinhtem.cpp:40: warning: friend declaration ‘Derived<T> operator+(T, Derived<T>)’ declares a non-template function
    netoprinhtem.cpp: In function ‘int main(int, char**)’:
    netoprinhtem.cpp:107: warning: converting to non-pointer type ‘double’ from NULL
    netoprinhtem.cpp: In member function ‘Derived<T> Derived<T>::eek:perator+(T) const [with T = double]’:
    netoprinhtem.cpp:115: instantiated from here
    netoprinhtem.cpp:71: warning: converting to non-pointer type ‘double’ from NULL
    /tmp/ccMrOSpk.o: In function `main':
    netoprinhtem.cpp:(.text+0xe5): undefined reference to `operator>>(std::basic_istream<char, std::char_traits<char> >&, Derived<double>&)'
    netoprinhtem.cpp:(.text+0xf8): undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Derived<double> const&)'
    netoprinhtem.cpp:(.text+0x41c): undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Derived<double> const&)'
    netoprinhtem.cpp:(.text+0x43d): undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Derived<double> const&)'
    netoprinhtem.cpp:(.text+0x45e): undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, Derived<double> const&)'

    If u can plese help me on this.
    Thankin you
     
  5. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    I think you have done some errors on your side. Try redoing it. I have edited the code to have the
    Code:
    using namespace std
    so now it should be fine as well. Thanks for pointing that out.
     
  6. rockoder

    rockoder New Member

    Joined:
    Jun 29, 2007
    Messages:
    2
    Likes Received:
    1
    Trophy Points:
    0
    Occupation:
    Software Developer
    Home Page:
    http://www.rockoder.com
    Your are facing a classic C++ problem.

    Replace following function declaration:
    friend ostream& operator << (ostream&,const Derived<T>&);

    to

    friend ostream& operator << <> (ostream&,const Derived<T>&);

    and also replace
    friend istream& operator >> (istream&,Derived<T>&);

    to

    friend istream& operator >> <>(istream&,Derived<T>&);

    Note: Only make change in function declaration and not in function definition.

    The problem is that you need to tell the compiler that the declared friend function is a template.

    Let me know if this works or if you face any problem.
     
    huckberry likes this.
  7. rockoder

    rockoder New Member

    Joined:
    Jun 29, 2007
    Messages:
    2
    Likes Received:
    1
    Trophy Points:
    0
    Occupation:
    Software Developer
    Home Page:
    http://www.rockoder.com
    Also note that this is a link time error not compile time:

    Original code should compile successfully using -c command:
    gcc -c code.cpp
     
  8. john21090

    john21090 New Member

    Joined:
    Aug 17, 2007
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    Hi,
    I am getting the following errors after applying the <> after the operator<< and operator>> as specified in a post above.
    Base.h:34: error: template-id 'operator<< <>' for 'std::basic_ostream<char, std::char_traits<char> >& operator<<(std::basic_ostream<char, std::char_traits<char> >&, const Derived<double>&)' does not match any template declaration
    Base.h:35: error: template-id 'operator>><>' for 'std::basic_istream<char, std::char_traits<char> >& operator>>(std::basic_istream<char, std::char_traits<char> >&, Derived<double>&)' does not match any template declaration
    Base.h: In function 'int main(int, char**)'

    Could someone please help?
    Thanks
     
  9. shabbir

    shabbir Administrator Staff Member

    Joined:
    Jul 12, 2004
    Messages:
    15,375
    Likes Received:
    388
    Trophy Points:
    83
    You don't need to apply <> after the operators but what is discussed is already incorporated in the above article and so you don't need to be doing anything.
     
  10. jogojapan

    jogojapan New Member

    Joined:
    Jul 12, 2008
    Messages:
    1
    Likes Received:
    2
    Trophy Points:
    0
    This reply may be somewhat late, but as I was facing a similar problem just now and found this discussion, let me add one important remark that anybody reading the above will find helpful.

    rockoder was right about the "<>" after the name of the function being necessary. The fact that shabbir is able to compile his code without adding it may indicate that he is using a compiler that is not very strict. But for example when using gcc 4.1, the "<>" is absolutely necessary to avoid the warnings and with ldd 2.7 it is necessary to avoid the linker errors.

    Now the reason why jijojs was still facing errors after making the correction is that a function (regardless of whether it is a template function or ordinary function) can never be declared "friend" of a class if its prototype wasn't declared before.

    So before the class definition of "Derived", you need the function prototype for the "operator<<" template. Moreover, because the operator<< takes an argument of type "Derived<T>", you must insert a forward-declaration of the class template, too.

    In the code this will look as follows:

    Code:
    template <typename T> class Derived;
    
    template <typename T>
    ostream& operator<<(ostream&,const Derived<T>&);
    
    template <typename T>
    istream& operator>>(istream&,Derived<T>&);
    
    template <typename T>
    class Derived : public Base<T>
    {
        public:
            //Default Functions also provided
            Derived(const T q = NULL): Base<T>(q){}
            Derived(const Derived &d): Base<T>(d.strQuery){}
            ~Derived(){}
            Derived<T> operator=(const Derived<T> d)
            {
                if(this != &d)
                    this->strQuery=d.strQuery;
                return *this;
            }
            
            //Input Output Functions 
            friend ostream& operator<< <>(ostream&,const Derived<T>&);
            friend istream& operator>> <>(istream&,Derived<T>&);
    
            //op + Functionality
            Derived<T> operator + (const Derived<T>) const;
            Derived<T> operator + (const T) const;
            friend Derived<T> operator + (const T,const Derived<T>);
            Derived<T>& operator ++ ();
            Derived<T>& operator ++ (int);
            Derived<T>& operator += (const Derived<T>);
    };
    
    You may also want to have a look at
    http://cboard.cprogramming.com/showthread.php?t=86607

    for a discussion of a similar situation and some alternative ideas.


    Another interesting problem arises when the class is defined in a special namespace, i.e. enclosed in something like this:

    Code:
    namespace special {
     ...
    }
    
    It is then important that the operator<< is also declared inside the same namespace. Theoretically it should be possible to make a non-namespace-specific global function a friend of a namespace-specific class, but at least gcc 4.1 does not allow you to do that.
     
    jpope19 and spikehazard like this.
  11. huckberry

    huckberry New Member

    Joined:
    Nov 9, 2010
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    Excuse me for poking a really old thread, but this is the most complete reference to template operator overloading I've found to date. My situation is very similar to the one in the example, except that instead of using Derived<T>& as the right hand side of the operator<<, I'm using Derived<T>::SubClass&. The error I'm getting from my compiler (M$ Visual Studio 2010) is this:

    Code:
    LinkedList.obj : error LNK2019: unresolved external symbol "class std::basic_ostream<char,struct std::char_traits<char> > & __cdecl operator<<(class std::basic_ostream<char,struct std::char_traits<char> > &,struct LinkedList<int>::Element const &)"  referenced in function _main
    1>LinkedList.exe : fatal error LNK1120: 1 unresolved externals
    
    Here's the relevant definitions:
    Code:
    template <class Type> class LinkedList {
    public:
    	struct Element{
    		friend ostream& operator<< ( ostream &output, const typename Element &E);
    	};
    };
    
    template <typename Type>
    ostream& operator <<(ostream& output, const typename LinkedList<Type>::Element& E){
    
    I've changed the definition of friend ostream& opertor << to include the <> however then I receive a different error, which makes me think that Visual Studio wont allow this type of function:

    Code:
    linkedlist.cpp(38): error C2785: 'std::ostream &operator <<(std::ostream &,const LinkedList<Type>::Element &)' and '<Unknown>' have different return types
    
    Any Idea why Visual Studio is comparing it to '<Unknown>'?
     
  12. huckberry

    huckberry New Member

    Joined:
    Nov 9, 2010
    Messages:
    2
    Likes Received:
    0
    Trophy Points:
    0
    Again, My apologies for poking an old thread.

    The issue was (eventually) resolved by removing the class Element from within the class LinkedList and making Element a template class.

    For future readers, Visual studio requires 'typename' in declarations and allows for the '<>' mentioned prior.

    Code:
    template < class Type > class Element {
    public:
        Type Data;
        friend ostream& operator << <>( ostream &output, const typename Element<Type> &E);
    }
    
    template < class Type > class LinkedList {
    public:
        Element<Type>&    operator[](int index);	 //For Left Hand Values
        const Element<Type>& operator[](int index) const; //For Right Hand Values
    }
    
    ostream& operator<<( ostream &output, const typename Element<Type>& E){
        return output << E.Data;
    }
    
    template <class Type> const typename Element<Type>& LinkedList<Type>::operator[](int index) const{
        Element<Type> Answer;
        //Logic Here
        return *Answer
    }
    
    int main(){
        LinkedList<int> Array1;
        //init and add memebers
        cout << Array1[0];
        return 0;
    
     
  13. jpope19

    jpope19 New Member

    Joined:
    Mar 8, 2012
    Messages:
    1
    Likes Received:
    0
    Trophy Points:
    0
    jogojapan just saved me a lot of time. thanks bro!
     

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice