Thread: Complex Number Class

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    14

    Complex Number Class

    Thanks again guys
    Last edited by Sephiroth1109; 12-12-2007 at 01:42 PM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You declared the destructor in your header, but never implemented it. Since the compiler generated destructor will work fine, do not declare the destructor. You also declared (and used, via operator<<) getReal() and getImaginary() but never implemented them.

    Other problems include:
    1. Using directives in header files are a Bad Thing. Remove the "using namespace std;" from your header file.

    2. Your header file should have an inclusion guard.

    3. Your overloaded operator<< for ostream should take the Complex object by const reference. It also does not need to be a friend since you have getReal() and getImaginary() which can be used to implement it.

    3. For const-correctness, getReal() and getImaginary() const member functions.

    4. Instead of including <iostream>, include <ostream> (and <istream>, for overloading operator>> for istream).

    5. You might want to provide a default constructor.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Apr 2006
    Posts
    2,149
    A minor point: there is no need to declare operator<< as a friend.

    Edit:
    also, your other operators should be prototyped in the header file.
    It is too clear and so it is hard to see.
    A dunce once searched for fire with a lighted lantern.
    Had he known what fire was,
    He could have cooked his rice much sooner.

  4. #4
    Registered User
    Join Date
    Nov 2007
    Posts
    14
    Thanks for the input. I've been going through my code and trying to make the changes you mentioned. I have a few questions and they are as follows

    1. when I call getReal() const; and getImaginary() const; what is the proper way of defining them in the class definition file? I got a few errors saying that the class I defined wasn't in the class.

    2. If I make a reference to Complex& how do I use the getReal() and getImaginary() function to get the doubles I need in order to print them out.

    3. Also, what exactly is an inclusion guard. Is that the ifndef stuff, I added that but I'm not sure about the format.

    Thanks for the help. And sorry about not including the two functions, after trying to figure this all out I was a little tired and forgot to include them, added them once then deleted them, forgot I didn't add them again.

  5. #5
    Registered User
    Join Date
    Nov 2007
    Posts
    14
    I figured out everything now, thanks guys. Just editing so no one can copy my hard work.
    Last edited by Sephiroth1109; 12-12-2007 at 01:42 PM. Reason: It was a school assignment, so I really don't want anyone else to see my hard work

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    What I had in mind was more along these lines:
    Code:
    #ifndef COMPLEX_H
    #define COMPLEX_H
    
    #include <ostream>
    #include <cstdlib>
    
    class Complex
    {
    public:
        Complex(double a, double b);
        double getReal() const;
        double getImaginary() const;
    
        Complex& operator+=(const Complex& rhs); 
        Complex& operator-=(const Complex& rhs);
        Complex& operator*=(const Complex& rhs);
        Complex& operator/=(const Complex& rhs);
    private:
        double dReal;
        double dImaginary;
    };
    
    Complex operator+(const Complex& a, const Complex& b); 
    Complex operator-(const Complex& a, const Complex& b);
    Complex operator*(const Complex& a, const Complex& b);
    Complex operator/(const Complex& a, const Complex& b);
    
    std::ostream& operator<<(std::ostream& out, const Complex& comp);
    
    #endif
    The idea is that operator<< does not need to be a friend as it can make use of getReal() and getImaginary(). Likewise the operator+, operator-, operator* and operator/ do not need to be friends. However, if you implement their respective assignment operators, you can then implement them in terms of these assignment operators, and thus provide a more complete interface.

    The errors you got was probably because you did not fully qualify ostream as std:stream.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Nov 2007
    Posts
    14
    Well I tried the code for the header file and I got zero compiler errors for the project but I got two runtime errors which are as follows.

    LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
    Debug/complex.exe : fatal error LNK1120: 1 unresolved externals

    not sure exactly what these are.

  8. #8
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    I don't understand why people make the real and imaginary values private in these sorts of classes. There is absolutely no restriction on the values these variables can take, you don't do anything special when they update, and the entire POINT of this class is to package the real and imaginary parts and make them easy to use.

    You didn't post your setReal() function, but I assume it looks like this:

    Code:
    void setReal(double a)
    {
        dReal = a;
    }
    In other words, the caller can set the value to whatever they please. Why not just make it public and allow them to do what they want instead of jumping through hoops?

    I think you are over-encapsulating.

  9. #9
    Registered User
    Join Date
    Nov 2007
    Posts
    14
    actually, I never really made one. With the java one I needed to, but I didn't bother for this one. Hopefully I don't think I need it, but yeah, that's exactly how it would look.

    Oh I looked up that particular linker error. It says it had something to do with the project type. This is supposed to be a console application and it is set like that. Is there something in my code that makes it otherwise?
    Last edited by Sephiroth1109; 12-12-2007 at 01:02 PM.

  10. #10
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by Sephiroth1109 View Post
    actually, I never really made one. With the java one I needed to, but I didn't bother for this one. Hopefully I don't think I need it, but yeah, that's exactly how it would look.
    Well, think for a while why dReal and dImaginary should be private. Will things go horribly wrong if outside users set these values to whatever they please? Are you ever going to do any special processing in the setReal() and setImaginary() functions? If not, the set() and get() stuff is just getting in the way.

    It's common to be a little forward-thinking and say, "Well in the future, I might want to add some additional stuff when one of these values changes, and so I need to encapsulate with an interface." In a lot of real world cases this is true, and it's a good habit to have, but this is a complex number class... Unless you are inventing some new kind of math, there is never going to be any restriction on the values those variables can take on.

  11. #11
    Registered User
    Join Date
    Nov 2007
    Posts
    14
    well thinking in the future is kind of pointless in this program, but I can see what you're saying. I was just trying to make it similar to my java version.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I don't understand why people make the real and imaginary values private in these sorts of classes. There is absolutely no restriction on the values these variables can take, you don't do anything special when they update, and the entire POINT of this class is to package the real and imaginary parts and make them easy to use.
    Realistically, in this case the definition of complex numbers will never change, and one is unlikely to calculate the real/imaginary parts (e.g., from polar coordinates) instead of storing and accessing them directly. On the other hand, in other cases one might provide getters/setters for all the member variables of the class to reserve the option of being able to calculate or somehow get these data without having to store them, or store them in a particular form.

    By the way, Sephiroth1109, if you really do need a complex number class, use std::complex from <complex>.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Nov 2007
    Posts
    14
    I need to create my own. I already know about the standard one. By the way, I looked up the linker error and some website told me to make a new project in visual C++ as a win32 dynamic linked library. The runtime errors dissappear, but I don't even know how to get an executable, looks like it made it a DLL file. soooo yeah

    Okay, I figured out the problem and I must say I feel like smashing this computer because of it. After further research I found out that linker error cannot find the main function. Sooo, I had one but the m was M. so I changed it to m and BINGO it worked. Such a small nuisance, I guess that's why you should never program when you're tired lol. Thanks again for all your help. I really really appreciate it.
    Last edited by Sephiroth1109; 12-12-2007 at 01:29 PM.

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
    Debug/complex.exe : fatal error LNK1120: 1 unresolved externals
    This problem is probably because you wrote "int Main()" instead of "int main()".

    I need to create my own. I already know about the standard one.
    Why not copy its interface?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by Sephiroth1109 View Post
    Well I tried the code for the header file and I got zero compiler errors for the project but I got two runtime errors which are as follows.

    LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
    Debug/complex.exe : fatal error LNK1120: 1 unresolved externals

    not sure exactly what these are.
    If you would look closely at errors like these, you should be able to spot it very easily. Everything in C++ in case sensitive. That is m != M.
    Since it says "_main" and you have "Main" I would very easily draw the conclusion that it should be "main" and not "Main."

    And FYI, Visual C++ 6 is an old compiler by now. If you can, I suggest you upgrade. Visual Studio 2008 Express is free, so you can use that unless you use MFC.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Number Guessing
    By blacknapalm in forum C Programming
    Replies: 2
    Last Post: 10-01-2008, 01:48 AM
  2. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 05:01 PM
  3. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM
  4. gcc problem
    By bjdea1 in forum Linux Programming
    Replies: 13
    Last Post: 04-29-2002, 06:51 PM
  5. Difficulty superclassing EDIT window class
    By cDir in forum Windows Programming
    Replies: 7
    Last Post: 02-21-2002, 05:06 PM