Operator overloading and inheritance with template classes.

shabbir's Avatar author of Operator overloading and inheritance with template classes.
This is an article on Operator overloading and inheritance with template classes. in C++.
Rated 5.00 By 1 users
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: Cpp
#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;
}
huckberry, WRaiTH likes this
jijojs's Avatar, Join Date: Jun 2007
Newbie Member
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::ostream& operator<<(std::ostream&, 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>::operator+(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..
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
You should replace
Code:
#include<iostream.h>
with
Code:
#include <iostream>
using namespace std;
jijojs's Avatar, Join Date: Jun 2007
Newbie Member
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::ostream& operator<<(std::ostream&, 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>::operator+(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
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
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.
rockoder's Avatar, Join Date: Jun 2007
Newbie Member
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 like this
rockoder's Avatar, Join Date: Jun 2007
Newbie Member
Also note that this is a link time error not compile time:

Original code should compile successfully using -c command:
gcc -c code.cpp
john21090's Avatar, Join Date: Aug 2007
Newbie Member
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
shabbir's Avatar, Join Date: Jul 2004
Go4Expert Founder
Quote:
Originally Posted by john21090
I am getting the following errors after applying the <> after the operator<< and operator>> as specified in a post above.
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.
jogojapan's Avatar, Join Date: Jul 2008
Newbie Member
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, spikehazard likes this