This is a grossly simplified version of what I am doing but gets the point across. I have 2 classes that can be used for arithmetic. My problem is I want to be able to multiply the 2 together but anyway I try this seems to cause a problem. For example:
class A {
uint32_t val_;
A(uint32_t src) {
val_=src;
}
friend A operator* (const A &a,const B &b); // <------ throws Unknown type B
};
class B {
uint32_t val_;
bool invert_;
B(A src,bool invert) {
val_=src.val_;
invert_=invert;
}
friend A operator* (const A &a,const B &b);
};
A operator* (const A &a,const B &b) {
if (b.invert_) return a.val_/b.val_;
return a.val_*b.val_;
}
how can I get around this seeming recursive error? If it wasn't for the B value always comes second I would put A operator* (const A &a); in the B class so I can just use friend class B in the A class
So the problem is I didn't know the term forward declaration.
class B; //forward declare B
class A {
uint32_t val_;
A(uint32_t src) {
val_=src;
}
friend A operator* (const A &a,const B &b);
};
class B {
uint32_t val_;
bool invert_;
B(A src,bool invert) {
val_=src.val_;
invert_=invert;
}
friend A operator* (const A &a,const B &b);
};
A operator* (const A &a,const B &b) {
if (b.invert_) return a.val_/b.val_;
return a.val_*b.val_;
}
simple fix when you know the term.
Related
I have seen many example to add objects of same class.I was trying to add two different class objects using operator overloading.
Code:
#include<iostream>
using namespace std;
class B;
class A
{
public:
int x;
A(int t=99)
{
x=t;
}
friend const A operator+( A& m, B& n);
friend ostream& operator<<(ostream& os, const A& c);
};
const A operator+(A& c1,B& c2)
{
A temp;
temp.x = c1.x + c2.y;
return temp;
}
ostream& operator<<(ostream &os, const A& c)
{
os << c.x;
return os;
}
class B
{
public:
int y;
B(int e=90)
{
y=e;
}
friend const A operator+( A& m, B& n);
};
int main()
{
A a,u;
B b;
u=a+b;
cout<<"Value of A+B"<<u;
return 0;
}
When i compiled my code it shows Error:
$ g++ operator_overloading.cpp
operator_overloading.cpp: In function ‘const A operator+(A&, B&)’:
operator_overloading.cpp:19:21: error: invalid use of incomplete type ‘struct B’
operator_overloading.cpp:3:7: error: forward declaration of ‘struct B’
What i have done wrong??
The error is clear. You have attempted to use members of B using only a forward declaration.
You have to define the operator after the definition of class B.
For example
#include<iostream>
using namespace std;
class B;
class A
{
public:
int x;
A(int t=99)
{
x=t;
}
friend const A operator+( const A& m, const B& n);
friend ostream& operator<<(ostream& os, const A& c);
};
ostream& operator<<(ostream &os, const A& c)
{
os << c.x;
return os;
}
class B
{
public:
int y;
B(int e=90)
{
y=e;
}
friend const A operator+( const A& m, const B& n);
};
const A operator+(const A& c1, const B& c2)
{
A temp;
temp.x = c1.x + c2.y;
return temp;
}
//...
Otherwise the compiler does not know what data members class B has.
Also it is better to define paraneters of the operator as constant references. In this case the operator can deal with temporary objects.
The error message is caused by the fact that you've defined your const A operator+(A& c1,B& c2) before defining the class B.
At this moment B is hence still an incomplete type (meaning you can only use pointers and references to it, but nothing else).
Just move this definition after you've defined B.
The line class B; forward-declares B. This tells the compiler that a class called "B" exists, but nothing else. When you attempt to use c2.y, where c2 is a B, the compiler does not yet know that B even has a y member.
One solution in this case is to move the definition of B so that it appears before the operator+ definition:
class B;
class A
{
public:
int x;
A(int t=99)
{
x=t;
}
friend const A operator+( A& m, B& n);
friend ostream& operator<<(ostream& os, const A& c);
};
class B
{
public:
int y;
B(int e=90)
{
y=e;
}
friend const A operator+( A& m, B& n);
};
const A operator+(A& c1,B& c2)
{
A temp;
temp.x = c1.x + c2.y;
return temp;
}
I have a bit of a problem with operator overloading and inheritance in C++.
Quick sketch:
class A {
public:
A operator+ (const A &b) const { ... }
};
class B : public A {
...
};
Now suppose I have two instances of B, x and y. If I add them I will get a thing of type A, however I want it to be of type B.
What is the best way of accomplishing this (aside from reimplementing them in class B) ? CRTP?
You can implement operator+ outside of the class as a template:
template<class type> type operator+(const type& left, const type& right)
{
type toReturn;
toReturn.value = left.value + right.value;
return toReturn;
}
class A {
private:
int value;
template <class type>
friend type operator+<type>(const type& left, const type& right);
};
class B : public A {
};
int main()
{
B test1, test2;
B test3 = test1 + test2;
}
This approach has certain down-sides. The compiler will aggressively try to instantiate the operator+ template for types which you don't want to define operator+, so be aware of that.
So I am making a program that has two classes monomial and polynomial. Basically a Polynomial is just an array of monomials. I need to create an operator + to add two monomials and return a polynomial. So far I have declared Polynomial as a friend class in monomial and friend Polynomial operator+(const Monomial& a, const Monomial& b); in class Polynomial but it doesnt seem to work.
friend Polynomial operator+(const Polynomial& a, const Monomial& b);
and
friend Polynomial operator+(const Monomial& a, const Polynomial& b);
both work fine so im very confused were the issue lies.
Here is a quick example program that compiles cleanly, of course the contents of Monomial and Polynomial can be changed to your liking.
#include <vector>
class Monomial
{
public:
Monomial() : A(0), x(0) {}
int A;
int x;
};
class Polynomial
{
public:
Polynomial() {}
Polynomial(const Monomial& a, const Monomial& b) {
monomials.push_back(a);
monomials.push_back(b);
}
std::vector<Monomial> monomials;
};
Polynomial operator+(const Monomial& a, const Monomial& b)
{
return Polynomial(a, b);
}
int main(int argc, char *argv[])
{
Monomial a;
Monomial b;
Polynomial poly = a + b;
return 0;
}
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Operator overloading
What causes C++ compiler error: must have argument of class or enumerated type?
I am trying to play a little bit with operator overloading and genericity in C++ and I seem to have 3 little errors when I try to compile. Have a class named Grandeur with template D, and then I inherit 3 classes from this one, named Temps(time), Longueur(size), Vitesse(speed), and I am trying to overload the operators such as when I do Temps+Temps->Temps, Vitesse+Vitesse=Vitesse,Longueur+Longueur->Longueur, Longueur/Time->Vitess etc.
In order not to write 3 times the same functions for the operations of same type, I use templates to utilise the genericity. But I have an error when I try to compile. Here is my code:
typedef double Longueur;
typedef double Temps;
typedef double Vitesse;
template<typename D>
class Grandeur {
protected :
double val; const char* unite;
public :
Grandeur(double qqc) : val(qqc) {}
Grandeur(int qqc) : val(qqc) {}
Grandeur(long qqc) : val(qqc) {}
Grandeur(float qqc) : val(qqc) {}
inline friend D operator+ (const D a, const D b) {
return D (a.val + b.val);
}
inline friend D operator- (const D a, const D b) {
return D (a.val - b.val);
}
inline friend double operator* (const D a, const D b) {
return a.val * b.val;
}
inline friend double operator/ (const D a, const D b) {
return a.val / b.val;
}
inline friend D operator* (D a, const int b) {
return D (a.val * b);
}
inline friend D operator/ (const D a, const int b) {
return D (a.val / b);
}
inline friend ostream& operator<< (ostream& os, D d) {
return os << d.val << d.u;
}
class Temps : public Grandeur<Temps> {
public:
};
class Vitesse : public Grandeur<Vitesse> {
public:
};
class Longueur : public Grandeur<Longueur> {
public:
};
};
inline Longueur operator* (const Vitesse v, const Temps t) {
return Longueur(v.val * t.val);
}
inline Vitesse operator/ (const Longueur l, const Temps t) {
return Vitesse(l.val / t.val);
}
inline Temps operator/ (const Longueur l, const Vitesse v) {
return Temps(l.val / v.val);
}
When I try to compile it says:
g++ essai.cc
In file included from essai.cc:4:0:
grandeurs.h:70:58: error: ‘Longueur operator*(Vitesse, Temps)’ must have an argument of class or enumerated type
grandeurs.h:74:58: error: ‘Vitesse operator/(Longueur, Temps)’ must have an argument of class or enumerated type
grandeurs.h:78:58: error: ‘Temps operator/(Longueur, Vitesse)’ must have an argument of class or enumerated type
The lines 70, 74 and 78 are those with the last 3 functions (the inlines). What can I do?
You're declaring the operators at global scope so the types Vitesse etc are not available to the compiler. Why not move the child classes outside Grandeur<T>'s definition?
EDIT for comment:
You're trying to use the operators with double values, but the implicit conversions are not automatically inherited by your child classes. You'll need to define them in each child and pass the parameters up to the parent template class.
It's time for my first question now. How do you cross assignments operators between two classes?
class B;
class A {
public:
A &operator = ( const B &b );
friend B &B::operator = ( const A &a ); //compiler error
};
class B {
public:
B &operator = ( const A &a );
friend A &A::operator = ( const B &b );
};
I searched for how to forward declare a member function like:
class B;
B &B::operator = ( const A &a ); //error
But I didn't find anything. And I don't want to make the classes all-out friends with each other. How do I do this?
There is no way to forward-declare member functions. I'm not sure if there is a more elegant way than this to get what you want (I've never had reason to do something like this), but what would work would be to make for the second class a non-member function that is a friend to both classes, and delegate copying to it. Note that operator= cannot be itself a non-member, but something like this should work:
class B;
class A {
public:
A& operator = ( const B &b );
friend B& do_operator_equals ( B& b, const A& b);
};
class B {
public:
B &operator = ( const A &a );
friend A& A::operator = ( const B &b );
friend B& do_operator_equals ( B& b, const A& a);
};
And then in your implementation file
A& A::operator= (const B& b) {
// the actual code to copy a B into an A
return *this;
}
B& B::operator= (const A& a) {
return do_operator_equals(*this, a);
}
B& do_operator_equals(B& b, const A& a) {
// the actual code to copy an A into a B
return b;
}
Edit: Got the A's and B's backwards, oops. Fixed.
The reason for the compiler error is a circular dependency. Each of your operator=() functions require knowledge of the operator=() function inside the other class, so no matter which order you define your classes in, there will always be an error.
Here is one way to sort it out. It isn't very elegant, but it will do what you want:
class A;
class B;
A & set_equal(A & a, const B & b);
B & set_equal(B & a, const A & a);
class A
{
private:
int x;
public:
A & operator=(const B & b) { return set_equal(*this, b); }
friend B & set_equal(B & b, const A & a);
friend A & set_equal(A & a, const B & b);
};
class B
{
private:
int y;
public:
B & operator=(const A & a) { return set_equal(*this, a); }
friend A & set_equal(A & a, const B & b);
friend B & set_equal(B & b, const A & a);
};
A & set_equal(A & a, const B & b) { a.x = b.y; return a; }
B & set_equal(B & b, const A & a) { b.y = a.x; return b; }
You may also be able to solve this problem with inheritance.
edit: here is an example using inheritance. This will work if the copying procedure only needs access to some common data shared by both A and B, which would seem likely if the = operator is to have any meaning at all.
class A;
class B;
class common
{
protected:
int x;
void copyFrom(const common & c) { x = c.x; }
};
class A : public common
{
public:
A & operator=(const common & c) { copyFrom(c); return *this; }
};
class B : public common
{
public:
B & operator=(const common & c) { copyFrom(c); return *this; }
};
Why do you want them to be friends in the first place?
This seem to be impossible the way you write it. The solution would probably be to not have them as friends at all.
You don't forward declare the member function, you forward declare the class.
class B; // DECLARE class B but don't define its contents
class A { // ... uses B as above
};
class B { // ... now you define the class.
};
See the C++ FAQ section 39.