DevX Home    Today's Headlines   Articles Archive   Tip Bank   Forums   

Page 1 of 2 12 LastLast
Results 1 to 15 of 23

Thread: Complex Number

  1. #1
    Join Date
    May 2007
    Posts
    843

    Thumbs up Complex Number

    Hello all C++ expert programmer, i have a dumb question.

    What is complex number ? What kind of function, complex class should have ?

    Below is my program :

    Code:
    
    // Header File for complex number
    
    #ifndef _Complex_
    #define _Complex_
    
    template <typename T>
    class complex
    {
    	T real, imaginary;
    
    public:
    	complex() : real(0), imaginary(0){}
    	explicit complex(T real, T imaginary)
    		: real(real), imaginary(imaginary){}
    	/* To enforce explicit conversion operation
           run successfully if one argument is supplied
        */
    
    	complex<T>(const complex<T> &complex)
    		:real(complex.real), 
    		imaginary(complex.imaginary){}
    	// Copy Constructor
    
    	T& operator=(const complex<T> &complex)
    	{
    		if (this != &complex)
    		{
    			real = complex.real;
    			imaginary = complex.imaginary;
    		} // To avoid self-assignment
    		return *this;
    	}
    	// Assignment Operator
    
    	void setReal();
    	void setImaginary();
    	
    	T& operator+(complex<T>);
    	T& operator-(complex<T>);
    	T& operator*(complex<T>);
    	T& operator/(complex<T>);
    
    
    
    	~complex(){}
    };
    
    #endif
    Implementation File :

    Code:
    #include<iostream>
    #include "Complex.h"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    	complex<double> a;
    
    	a.setReal();
    	a.setImaginary();
    
    	complex<double> b;
    
    	b.setReal();
    	b.setImaginary();
    
          
          cout <<  a.operator+(b);
         // Run error, cannot execute 
    
    
    
    	return 0;
    
    }
    // ---------------------------------------
    template<typename T>
    void complex<T>::setReal()
    {
    	cout << "Enter the real number : ";
    	cin >> real;
    }
    // ---------------------------------------
    template<typename T>
    void complex<T>::setImaginary()
    {
    	cout << "Enter the imaginary number : ";
    	cin >> imaginary;
    }
    // ---------------------------------------

    cout << a.operator+(b);
    // Run error, cannot execute


    I don't know what happen. It just cannot execute.

    Complex.obj : error LNK2001: unresolved external symbol "public: double & __thiscall complex<double>::operator+(class complex<double>)" (??H?$complex@N@@QAEAANV0@@Z)
    Thanks for your help.
    Your help is greatly appreciated by me and others.

  2. #2
    Join Date
    Jan 2005
    Location
    UK
    Posts
    604
    Hi,
    you did not implement your + operator.
    Since you created a template class, the implementation should be in the *SAME* file, either inlined in the class declaration or outside. Don't implement it in another file, or you have to include it as well. Remember: a template class is not compiled and linked like other classes, but only when referenced in your code. You can even write methods that are not compiling when you reference them, but if you do not reference them you won't find out. It's a pecularity of templates that you got to get used to.

    So implement your + operator and you should be cooking with gas...

    Cheers,

    D

  3. #3
    Join Date
    Jan 2007
    Posts
    145
    complex number is just an object with two varible re and im.
    Define + operator and see.

  4. #4
    Join Date
    May 2007
    Posts
    843
    This is a noob question i ever ask. I forgot to implement the definition.

    Thanks for your remind. I will implement it in a same file.

  5. #5
    Join Date
    May 2007
    Posts
    843

    Thumbs up

    I have implement the definition but come out some errors such as
    d:\c++\complex number\complex number\complex.h(45) : error C2440: 'return' : cannot convert from 'complex<T>' to 'double &'
    Code:
    
    // Header File for complex number
    
    #ifndef _Complex_
    #define _Complex_
    
    template <typename T>
    class complex
    {
    	T real, imaginary;
    
    public:
    	complex() : real(0), imaginary(0){}
    	explicit complex(T real, T imaginary)
    		: real(real), imaginary(imaginary){}
    	/* To enforce explicit conversion operation
           run successfully if one argument is supplied
        */
    
    	complex<T>(const complex<T> &complex)
    		:real(complex.real), 
    		imaginary(complex.imaginary){}
    	// Copy Constructor
    
    	T& operator=(const complex<T> &complex)
    	{
    		if (this != &complex)
    		{
    			real = complex.real;
    			imaginary = complex.imaginary;
    		} // To avoid self-assignment
    		return *this;
    	}
    	// Assignment Operator
    
    	void setReal();
    	void setImaginary();
    	
    	T& operator+(complex<T> second)
    	{
    		this->real = real + second.real;
    		this->imaginary = imaginary + second.imaginary;
    		
    		return *this;
    	}
    
    	T& operator-(complex<T>);
    	T& operator*(complex<T>);
    	T& operator/(complex<T>);
    
    
    
    	~complex(){}
    };
    
    #endif
    Thanks for your help.

  6. #6
    Join Date
    Jan 2005
    Location
    UK
    Posts
    604
    Hi,
    a few glitches again:
    Code:
    T& operator=(const complex<T> &complex) // you call your variable the same as your class!!
                                                                        // use rhs, or similar instead
                                                                        // I should be surprised if this code compiles
    
    // I would implement your + operator in the following way
    	complex<T>& operator+=(const complex<T>& second)
    	{
    		real += second.real;
    		imaginary += second.imaginary;
                             return *this;
                  }
    // outside the class: global + operator
    template <class T>
    complex<T> operator + (const complex<T>& lhs, const complex<T>& rhs)
    {
        complex<T> reval = lhs;
        reval += rhs;
        return reval;
    }
    This way you have a symmetric operator and you can use it as you would intuitively.

    Hope that helps.

    D

    BTW: your original error was, that your + operator returned a T rather than a complex<T> ....
    DKyb
    -------------------------------
    Life is a short warm moment -
    Death is the long cold rest.
    Pink Floyd
    -------------------------------

  7. #7
    Join Date
    May 2007
    Posts
    843

    Thumbs up

    I think i very stupid because such a simple program also couldn't wrote it well.

    I understand few statement that you explain.

    T& operator=(const complex<T> &complex) // you call your variable the same as your class!!
    I know that complex(){} (constructor) is same as complex<T>(){} but how me this concept couldn't applied to this situation

    T& operator+(const complex<T> second(){}

    The second unclear is why u further implement + operator as global function.


    I really very stupid. Please forgive my stupidness.

    Thanks for your help.

    Your help is greatly appreciated by me and others.

  8. #8
    Join Date
    Jan 2005
    Location
    UK
    Posts
    604
    Hi,
    the reason why you should implement a global operator:
    Code:
    // when you implement a + operator inside the class, like you did, the
    // following will happen:
    complex<double> c1(1.0,1.0);
    complex<double> c2(-1.0,2.0);
    complex<double> c3 = (c1 + c2); // ooops: c1 is now (0.0,3.0) !!!!
    // moreover the operator is not symmetric in that
    complex<double> c3 = (c2 + c1); // ooops: c2 is now (0.0,3.0) !!!!
    I don't think your questions are at all stupid. Most people stumble across these subtelties of C++ when they learn the language... ;-)

    Cheers,
    D

  9. #9
    Join Date
    May 2007
    Posts
    843
    Thanks for your help. You are really good man.

    By the way, i test it according what you say. The first argument (c1 or c2) is override by the result c3. It's so miracle.

    Why such matter happen because they all all different object ?

    Thanks for your help. I really admire you because you have deep C++ knowledge.

  10. #10
    Join Date
    May 2007
    Posts
    843

    Thumbs up

    I have did what you told but still will override the first argument of the expression -> c=a+b;

    a will get override by c.

    As i know, return reference is undefined behavior but i feel unclear about this rules.

    Someone says cannot return local reference but can return the reference from the paramater. Which one is true ?


    Below is my program:

    Header File :

    Code:
    
    // Header File for complex number
    
    #ifndef _Complex_
    #define _Complex_
    
    #include<iostream>
    
    using std::ostream;
    
    template <typename T>
    class complex
    {
    	T real, imaginary;
    	friend ostream& operator<<(ostream& output, const complex<T> any)
    	{
    		output << "\nThe result of real is " << any.real 
    			<< "\nThe result of imaginary is " << any.imaginary;
    
    		return output; 
    		// Reference is pass by reference without * or & same pass by value;
    	}
    
    public:
    	// Complex(){} is same complex<T>(){}
    	complex<T>() : real(0), imaginary(0){}
    	explicit complex(T real, T imaginary)
    		: real(real), imaginary(imaginary){}
    	/* To enforce explicit conversion operation
           run successfully if one argument is supplied
        */
    
    	complex<T>(const complex<T> &complex)
    		:real(complex.real), 
    		imaginary(complex.imaginary){}
    	// Copy Constructor
    
    	complex<T>& operator=(const complex<T> &complex)
    	{
    		if (this != &complex)
    		{
    			real = complex.real;
    			imaginary = complex.imaginary;
    		} // To avoid self-assignment
    		return *this;
    	}
    	// Assignment Operator
    
    	void setReal();
    	void setImaginary();
    	
    	complex<T>& operator+(complex<T> second)
    	{
    		this->real = real + second.real;
    		this->imaginary = imaginary + second.imaginary;
    		
    		return *this;
    	}
    
    	complex<T>& operator-(complex<T> second)
    	{
    		real -= second.real;
    		imaginary -= second.imaginary;
    
    		return *this;
    	}
    	complex<T>& operator*(complex<T> second)
    	{
    		real *= second.real;
    		imaginary *= second.imaginary;
    
    		return *this;
    	}
    
    	complex<T>& operator/(complex<T> second)
    	{
    		real /= second.real;
    		imaginary /=second.imaginary;
    
    		return *this;
    	}
    
    
    
    	~complex(){}
    };
    
    template <typename T>
    complex<T>& operator+(const complex<T> first, const complex<T> second)
    {
    	complex<T>& reference = first;
    	reference += second;
    
    	return reference;
    }
    
    
    #endif

    Implementation File :

    Code:
    #include<iostream>
    #include "Complex.h"
    
    using namespace std;
    
    int main(int argc, char *argv[])
    {
    	complex<double> a;
    
    	a.setReal();
    	a.setImaginary();
    
    	complex<double> b;
    
    	b.setReal();
    	b.setImaginary();
    
    	/* Explicit Function call
    	   The first argument will override
    	   by result.Exp: a will overrride by result
        */
    	cout << a+b;  
    	cout << a << b;
    	// This call must define own insertion operator;
    	// If have get function no need define <<
    /*	cout << a.operator-(b);
    	cout << a.operator*(b);
    	cout << a.operator/(b);*/
    	
        // Shortcut cout << a+b
    
    
    
    	return 0;
    
    }
    // ---------------------------------------
    template<typename T>
    void complex<T>::setReal()
    {
    	cout << "Enter the real number : ";
    	cin >> real;
    }
    // ---------------------------------------
    template<typename T>
    void complex<T>::setImaginary()
    {
    	cout << "Enter the imaginary number : ";
    	cin >> imaginary;
    }
    // ---------------------------------------
    Thanks for your help.

  11. #11
    Join Date
    Jan 2005
    Location
    UK
    Posts
    604
    Hi,
    You still have the + - operator implemented as a member.
    just change all your arithmetic operatorslike that:
    Code:
    	complex<T>& operator+=(complex<T> second)
    	{
    		this->real = real + second.real;
    		this->imaginary = imaginary + second.imaginary;
    		
    		return *this;
    	}
    
    	complex<T>& operator-=(complex<T> second)
    	{
    		real -= second.real;
    		imaginary -= second.imaginary;
    
    		return *this;
    	}
    	complex<T>& operator*=(complex<T> second)
    	{
    		real *= second.real;
    		imaginary *= second.imaginary;
    
    		return *this;
    	}
    
    	complex<T>& operator/=(complex<T> second)
    	{
    		real /= second.real;
    		imaginary /=second.imaginary;
    
    		return *this;
    	}
    and implement the global operators +,-,*,/ in terms of these operators.
    Don't implement the +,-,/,* operators at all as members.

    When you use e.g. += you explitely want the left hand side modified, that's why operator assignment - operators do the right thing.
    Code:
    complex<double> c1(1.0,-1,0);
    complex<double> c2(2.0,0.0);
    
    c2 += c1; // c2 is now (3.0,-1.0) and c1 unchanged: correct.
    Cheers,
    D

  12. #12
    Join Date
    May 2007
    Posts
    843

    Thumbs up

    **** drybelk, i finally understand why the +, -, * and / should declared as global because to enforce symmetrical.

    Now i have few problem regarding template.

    I hope you all can help me out.


    Header File.
    Code:
    // Header File for complex number
    
    
    
    #ifndef _Complex_
    
    #define _Complex_
    
    
    
    #include<iostream>
    
    using std::ostream;
    
    
    
    template<typename T>
    class complex;
    // Forward Declaration
    
    // symmetrical between first and second
    template<typename T>
    complex<T>& operator+
    (const complex<T>& first, const complex<T>& second);
    
    template <typename T>
    
    class complex
    
    {
       T real, imaginary;
    
    
       public:
       friend ostream& operator<<(ostream& output, const complex<T> any)
    
       {
    
           output << "\nThe result of real is " << any.real << "\nThe result of imaginary is " << any.imaginary;
    
    
    
           return output; 
    
           // Reference is pass by reference without * or & same pass by value;
    
       }
    
    
       // Complex(){} is same complex<T>(){}
    
       complex<T>() : real(0), imaginary(0){}
    
       explicit complex(T real, T imaginary)
    
    		: real(real), imaginary(imaginary){}
    
       /* To enforce explicit conversion operation
    
           run successfully if one argument is supplied
    
        */
    
       complex<T>(const complex<T> &complex)
    
    		:real(complex.real), 
    
    		imaginary(complex.imaginary){}
       // Copy Constructor
    
    		
    	
       complex<T>& operator=(const complex<T> &complex)
    		
       {
    
          if (this != &complex)
    
          {
    
             real = complex.real;		imaginary = complex.imaginary;
    
          } // To avoid self-assignment
    
         
          return *this;
    
       }
    
       // Assignment Operator
    
       
       friend complex<T>& operator +
       (const complex<T>& first, const complex<T>& second)
       {
         complex<T>& result = first;
         // reference must be initialized
         result = first.real + second.real;
         result = first.imaginary + second.imaginary;
               
         return result;
         
       }
    
    
       void setReal();
    
       void setImaginary();
    
    	
    
       ~complex(){}
    
    };
    
    
    #endif
    Error Message is as follow.

    T' was not declared in this scope
    template argument 1 is invalid
    'T' was not declared in this scope
    template argument 1 is invalid
    'T' was not declared in this scope
    template argument 1 is invalid
    invalid type in declaration before ';' token
    'int& operator+(const int&, const int&)' must have an argument of class or enu
    In function 'complex<double>& operator+(const complex<double>&, const
    error: invalid initialization of reference of type 'complex<double>&' from expression of type 'const comple




    This is all the error message i got from gcc compiler.
    I using kdevelop.


    Thanks for your help.

    Your help is greatly appreciated by me and others.
    Last edited by Peter_APIIT; 07-18-2007 at 05:27 AM.

  13. #13
    Join Date
    Jul 2007
    Posts
    25
    I don't have gcc to try it myself but why gcc? have you tried to compile it with g++ as well?

  14. #14
    Join Date
    Jul 2007
    Posts
    25
    I tried it with an IBM compiler that I can use at the moment, because I am at work, (xlc++) in AIX and your code compiles fine.

  15. #15
    Join Date
    May 2007
    Posts
    843
    What the difference between gcc and g++? Gnu Compiler collection(gcc) already included the g++ compiler.

Similar Threads

  1. Replies: 18
    Last Post: 12-13-2006, 03:49 PM
  2. Prime number program to make go faster
    By divagoddess in forum C++
    Replies: 12
    Last Post: 05-07-2006, 10:55 PM
  3. Complex class won't compile
    By Mcody2 in forum Java
    Replies: 7
    Last Post: 12-02-2005, 12:29 AM
  4. Complex number
    By burung in forum Java
    Replies: 3
    Last Post: 08-01-2005, 05:59 AM
  5. Help
    By George in forum oracle.general
    Replies: 0
    Last Post: 04-01-2003, 01:00 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
HTML5 Development Center
 
 
FAQ
Latest Articles
Java
.NET
XML
Database
Enterprise
Questions? Contact us.
C++
Web Development
Wireless
Latest Tips
Open Source


   Development Centers

   -- Android Development Center
   -- Cloud Development Project Center
   -- HTML5 Development Center
   -- Windows Mobile Development Center