Go4Expert

Go4Expert (http://www.go4expert.com/)
-   C++ (http://www.go4expert.com/articles/cpp-tutorials/)
-   -   Operator overloading and inheritance with template classes. (http://www.go4expert.com/articles/operator-overloading-inheritance-t4257/)

shabbir 10May2007 11:19

Operator overloading and inheritance with template classes.
 
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;
}


jijojs 14Jun2007 21:48

Re: Operator overloading and inheritance with template classes.
 
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 14Jun2007 21:53

Re: Operator overloading and inheritance with template classes.
 
You should replace
Code:

#include<iostream.h>
with
Code:

#include <iostream>
using namespace std;


jijojs 14Jun2007 22:03

Re: Operator overloading and inheritance with template classes.
 
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 15Jun2007 09:00

Re: Operator overloading and inheritance with template classes.
 
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 29Jun2007 22:53

Re: Operator overloading and inheritance with template classes.
 
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.

rockoder 29Jun2007 23:00

Re: Operator overloading and inheritance with template classes.
 
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 17Aug2007 19:24

Re: Operator overloading and inheritance with template classes.
 
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 18Aug2007 07:40

Re: Operator overloading and inheritance with template classes.
 
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 12Jul2008 19:08

Re: Operator overloading and inheritance with template classes.
 
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.


All times are GMT +5.5. The time now is 03:53.