-1

I don't dabble in C++ very often, but I'm learning about data structures and the book uses c++ as it language. I'm currently going over setting up classes.

My issues are:

  1. Visual Studio 2012 is barking about unidentified variables. I have the variables declared in my header, so I'm not quite sure why I'm having the issue.

  2. I'm trying to overload the addition and multiplication operators (as non-member functions) but it is still trying to use it as if I'm only allowed to have one parameter for the overload.

Here is some code for what I'm doing:

1. Unidentified variables

/* Quadratic.h */

#include <iostream>
using namespace std;

class Quadratic 
{
 public: 
     // constructors
     Quadratic::Quadratic()

     // accessors
     Quadratic::getA();
     Quadratic::getB();
     Quadratic::getC();

     // mutators
     Quadratic::setCoefficients(float coA, float coB, float coC);

private:
    float a, b, c, x;

};

Quadratic.cpp:

/* Quadratic.cpp */

#include <iostream>
#include "Quadratic.h"
using namespace std;

class Quadratic 
{

 // Default constructor
 Quadratic::Quadratic() 
 {
     a = 0;    // Visual Studio is complaining about a, b, & c
     b = 0; 
     c = 0;
 }

 /* Mutators */
 void Quadratic::setCoefficients(float coA, float coB, float coC) 
 {
     a = coA;
     b = coB;
     c = coC;
 }

 /* Accessors */
 float Quadratic::getA() const {
     return a;
 }

 float Quadratic::getB() const {
     return b;
 }

 float Quadratic::getC() const {
     return c;
 }

};

So that is what the first issue is about. I'm not quite sure why it isn't able to find those variables. Can someone point out what I'm doing wrong?

2. Overloading Operator (mismatch on the parameters)

/* Quadratic.h */

/* Overloading Operators */
Quadratic & operator+(const Quadratic & q1, const Quadratic & q2);
Quadratic & operator*(double r, const Quadratic & q);

It is simply telling me that I have too many parameters. I'm thinking it is expecting to do something like q1.operater+(q2) where as I'm wanting to be able to do something like q3 = q1 + q2

Any pointers would be great for fixing these small issues.

Edit

Compiler errors as requested:

error C2804: binary 'operator +' has too many parameters
error C2804: binary 'operator *' has too many parameters

Basically what I mentioned above, perhaps I wasn't clear about it though.

Edit 2

Not sure why it was downvoted, but if you're going to downvote it, at least state why... If it was because the question was novice? Because the question was poorly worded or explained, or just because your ego is too high? No need to put someone down when they are attempting to learn something new.

Other than that, thank you legend2k, john, steve, salda and basile for all taking the time to help me out. I really do appreciate it. C++ is a lot more hands on than Java.

StartingGroovy
  • 2,802
  • 9
  • 47
  • 66
  • 2
    Putting up the actual compiler error may help. – legends2k Oct 12 '13 at 19:33
  • @legends2k I haven't created my main yet, so I've yet to compile it. I was simply wondering why my IDE was barking at me. The first issue was solved by removing `class Quadratic {}` from the .cpp. I still have the operator problem though. *Edit* Added the compiler error for the second issue. – StartingGroovy Oct 12 '13 at 19:41
  • 2
    Your overload problem is because you are declaring them inside your class. Move them outside your class and it will be OK. Everything in a class gets an implicit extra parameter which is the object being operated on. Also another error, your operators should not return a reference. Not sure where you got that from but it's wrong. This `Quadratic operator+(const Quadratic & q1, const Quadratic & q2);` outside the class is correct. – john Oct 12 '13 at 19:46
  • 2
    Additionally, the prototype of the `operator+` function shows that you're returning a reference, but you want `q3 = q1 + q2` to work, for which you've to return by value a new object and not a reference to an existing object. See [this post](http://stackoverflow.com/q/4421706/183120) for details on operator overloading. – legends2k Oct 12 '13 at 19:48
  • @john Thank you for explaining this. Sorry, I'm new to C++ and reading quite a bit on it. I was unaware that it is to be placed outside of the class. But I appreciate you pointing this out. – StartingGroovy Oct 12 '13 at 20:01
  • 1
    @StartingGroovy Just noticed the question '(as non-member functions)', that means outside the class. – john Oct 12 '13 at 20:04

4 Answers4

5

In your Quadratic.cpp you need to remove the line:

class Quadratic 
{

As this is hiding your definition of Quadratic in the header file. However, this is hiding errors in your header file. In the .h file you must specify the return types of the methods and you do not need to qualify the method names with Quadratic. To fix the operator overloading error make sure that they are declared outside of the class declaration in your header file.

class Quadratic {
     //...
     // accessors
     float getA() const;
     float getB() const;
     float getC() const;

     // mutators
     void setCoefficients(float coA, float coB, float coC);

     // rest of class definition as in question...

};   // end of class declaration

Quadratic & operator+(const Quadratic & q1, const Quadratic & q2);
Quadratic & operator*(double r, const Quadratic & q);

Overloading operators can cause subtle bugs. I strongly urge you to read this page to avoid the common pitfalls: Operator overloading

Community
  • 1
  • 1
Steve
  • 7,171
  • 2
  • 30
  • 52
  • This fixed it. Very odd, I wasn't aware that we weren't supposed to add `class Quadratic {}` is it because we already have it in our header? – StartingGroovy Oct 12 '13 at 19:38
  • @StartingGroovy Yes, in C++ you typically declare and then define functions and classes. Typically, you declare them (i.e. say the exist) in header files and define them in implementation (cpp) files. See http://www.cprogramming.com/declare_vs_define.html – Steve Oct 12 '13 at 19:43
  • If I understand it correctly, I don't need to use the scope operator ie. `Quadratic::` in the header because it has the class defined in there. But I need to in the use the scope operators in the .cpp because it is searching through various headers or libraries for said function. Any clue about the operator overloading issue? – StartingGroovy Oct 12 '13 at 19:54
  • @StartingGroovy you understand correctly. As for the operator overloads: are those declarations inside the `class` or free-standing (i.e. outside the class) in your header file? If they are *inside* the class, that's a problem. Remember that class member functions takes a "hidden" parameter (the `this` pointer) which identifies the object on which the member function was invoked. So this would cause your operator overloads to have *three* arguments, which can't work, since we know that binary `+` and `*` take, by definition, exactly two arguments. – Nik Bougalis Oct 12 '13 at 20:03
2

Looks like you are re declaring your whole class. In C++, you say class once to declare the interface (usually in the h file), and then go about defining the methods (usually in the cpp file). By saying class in the two files you are re declaring the class instead of defining the implementation.

Also, you don't need to say Quadratic:: inside the class declaration, since the class keyword makes it where anything you declare inside it is by definition inside the class scope. In contrast, when you write your implementation, you do need to prepend Quadratic:: because you are no longer inside the class scope.

Last, you also need not "use" namespace std twice. It's enough to put it in the h file before the class declaration; it'll also be accessible from the class implementation in the cpp file because the cpp file includes the h file.

SaldaVonSchwartz
  • 3,769
  • 2
  • 41
  • 78
  • Thanks, fixed each issue you mentioned. Silly mistakes from misunderstanding the material on my part. I'm still confused about overloading the operator though. – StartingGroovy Oct 12 '13 at 19:58
2

Move the operator+ and operator* functions outside of the class as John suggested. However, you've to make those functions friends of the class as you need access to the private variables of the objects.

Additionally, you've declared the operator functions as returning references, but for the syntax you need q3 = q1 + q2;, you've to return by value after constructing a new object. So after removing the current operator+ and operator* functions, you've to do

class Quadratic
{
    . . .
    friend Quadratic operator+ (const Quadratic &lhs, const Quadratic &rhs);
    friend Quadratic operator+ (double scalar, const Quadratic &rhs);
}

Quadratic operator+ (const Quadratic &lhs, const Quadratic &rhs)
{
    Quadratic result;
    result.setCoefficients(lhs.a + rhs.a, lhs.b + rhs.b, lhs.c + rhs.c);
    return result;
}

If you made your constructor like this

Quadratic::Quadratic(float coA = 0.f, float coB = 0.f, float coC = 0.f) :
    a(coA),
    b(coB),
    c(coC),
    x()
{
}

i.e. with default arguments, you can write the operator function in a single line:

Quadratic operator+ (const Quadratic &lhs, const Quadratic &rhs)
{
    return Quadratic(lhs.a + rhs.a, lhs.b + rhs.b, lhs.c + rhs.c);
}

This will facilitates return value optimization (RVO) which will avoid copies. Also in constructors using initialization lists than member assignment is better.

Community
  • 1
  • 1
legends2k
  • 31,634
  • 25
  • 118
  • 222
  • Thanks for all this information legends2k. I may be back with more questions in the next hour or so :) hope you're still around looking for a new question! – StartingGroovy Oct 12 '13 at 21:35
  • Just an FYI, when trying to make the operators into friend operators, I think it needs to be `friend Quadratic operater ...` otherwise there is a syntax error. But this is still telling me that my variables are inaccessible. – StartingGroovy Oct 12 '13 at 23:01
  • Oh true, I missed the return type in the friend declaration. Fixed it in the answer now. – legends2k Oct 13 '13 at 03:06
1

The usual way is to initialize member variables (i.e. fields) in the constructor before its body:

Quadratic::Quadratic() : a(0), b(0), c(0), x(0) {};

Then I would believe the compiler would consider the fields as initialized. (at least GCC does).

And you could declare some operators inside the class, see here:

class Quadratic {
  Quadratic & operator += (const Quadratic&right);

You could declare it outside of the class, e.g.

  Quadratic operator + (const Quadratic& left, const Quadratic& right);

As others told you, you probably want to return a value, not a reference.

notice that *this is the left operand, which you should usually return.

BTW, please show the exact error messages you have got, and their precise location.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 2
    Is this an answer, really? It'd be better off as a comment but not as an answer. – legends2k Oct 12 '13 at 19:35
  • Yeah, that is what the book mentioned as well. Coming from java, that looks very odd to me. So I simply did it the way I was used to. However, when I tried this before posting it was giving the same issue. @Steve's answer above fixed issue #1. But I have a question, is it considered improper initializing the variables like I did above? – StartingGroovy Oct 12 '13 at 19:37
  • @StartingGroovy: It's is allowed the way you've done it; however this method here, called the [initializer lists](http://www.parashift.com/c++-faq-lite/init-lists.html), is better and may be more performant. – legends2k Oct 12 '13 at 19:45
  • Thanks for the clarification legends2k. Also thanks for the reply Basile – StartingGroovy Oct 12 '13 at 20:02