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;
}
Related
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.
What operators I need to overload to make this word?
Variables A1 and A2 both of type class A, variable floatValue is of type float.
A1 += A2 * floatValue;
I have overloaded this operators
A operator+() const;
A operator+=(const A value);
A operator*(const A value);
friend A operator*(const A val2, float val);
But, I receive error "Class A has no suitable copy constructor"
I have this constructors in my class
A();
A(float val1, float val2);
A(float value);
Thanks for answering.
Minimal example:
#include <iostream>
using namespace std;
struct foo {
float val;
foo(float val): val(val){}
foo &operator+=(foo const &other) {
this->val += other.val;
return *this;
}
friend foo operator*(foo const &lhs, foo const &rhs) {
return lhs.val*rhs.val;
}
};
int main() {
foo a = 5, b = 6;
a += b * 3;
cout << a.val << endl;
return 0;
}
see: http://ideone.com/6pD2pr
With an explicit constructor you might want to use this example instead:
#include <iostream>
using namespace std;
struct foo {
float val;
explicit foo(float val): val(val){}
foo &operator+=(foo const &other) {
this->val += other.val;
return *this;
}
friend foo operator*(foo const &lhs, float val) {
return foo(lhs.val*val);
}
};
int main() {
foo a(5), b(6);
a += b * 3;
cout << a.val << endl;
return 0;
}
see: http://ideone.com/o8Vu1d
Whenever you overload an assignment operator like
A operator+=(const A value);
you also need to define a copy constructor like
A( const A& );
The copy constructor will be used by the assignment operator.
This is part of what's known as the Rule of Three.
When you have function like this:
fun(A a);
Arguments here are passed by value, so you need to have copy constructor for A (in order to create new instance from another instance), OR you can change it to reference, so no copy constructor will be needed.
Like this:
A operator+=(const A &value);
Hello dear StackOverflowers!
I am having trouble with a template structure which comprises another (but non-template) structure.
Here's the thing:
Structure B is non-template and is defined inside a template structure A.
Strcure B is "protected" because it exists only for the purposes of structure A and no-one and nothing else shall use it outside of structure A.
There's an overload of operator<< for structure B, so that objects of type B can be sent to the standard output "cout << B_type_object;" (and it's A's friend so that it can access B which is protected).
The aforementioned printing of B objects is done only by methods defined in A (because of "2.").
As long as both structures are non-template everything works like a charm.
The moment A is a template I get an error message (provided in the code section).
Here is the working code (where A is not template):
#include <iostream>
#include <string>
struct A
{
protected:
struct B
{
std::string something;
B& operator= (const std::string&& rhs)
{
this->something = std::move(rhs);
return *this;
}
};
B B_object;
friend std::ostream& operator<< (std::ostream& output, const typename A::B& ob);
public:
void method ()
{
B_object = "This is text.";
//No error here
std::cout << B_object;
}
};
std::ostream& operator<< (std::ostream& output, const typename A::B& ob)
{
output << ob.something;
return output;
}
int main(int argc, const char * argv[])
{
A obj;
obj.method();
return 0;
}
This is the code which doesn't work
#include <iostream>
#include <string>
template <typename T>
struct A
{
T variable;
protected:
struct B
{
std::string something;
B& operator= (const std::string&& rhs)
{
this->something = std::move(rhs);
return *this;
}
};
B B_object;
template <typename X> friend std::ostream& operator<< (std::ostream& output, typename A/*<X>*/::B& ob);
public:
void method ()
{
B_object = "This is text.";
//ERROR: Invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'A<int>::B')
std::cout << B_object;
}
};
template <typename X>
std::ostream& operator<< (std::ostream& output, typename A<X>::B& ob)
{
output << ob.something;
return output;
}
int main(int argc, const char * argv[])
{
A<int> obj;
obj.method();
return 0;
}
Just declare the operator inline in B, then it works:
...
struct B
{
std::string something;
B& operator= (const std::string&& rhs)
{
this->something = std::move(rhs);
return *this;
}
friend std::ostream& operator<< (std::ostream& output, const typename A<T>::B& ob)
{
output << ob.something;
return output;
}
};
...
This has also the advantage that your are not friending any operator<< of any A<X>. In your example, the operator taking A<string>::B would also be a friend of A<int>::B. For a more in-depth explanation, see this answer:
https://stackoverflow.com/a/4661372/36565
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.