I have this snippet of the code:
header
class A {
private:
int player;
public:
A(int initPlayer = 0);
A(const A&);
A& operator=(const A&);
~A();
void foo() const;
friend A& operator=(A& i, const A& member);
};
operator=
A& operator=(A& i, const A& member){
i(member.player);
return i;
}
and I have row in my code:
i = *pa1;
A *pa1 = new A(a2);
at the beginning i was int
how can I fix it, thanks in advance
I have an error must be non-static function
The assignment operator for a class must be a member function, not a friend.
A& operator=( const A& member){
this->player = member.player);
return *this;
}
If you want to convert an A class object to an integer, provide a named conversion function such as ToInt().
As with all your questions, this could easily have been answered by reading a C++ text book. This is the last of such questions from you I will be answering.
Related
I'm working on a project attempting to implement a stand-alone base class (A) that can be extended by later classes (such as B and C). I want to be able to use them all independently, hence no pure virtual functions, and I want only one copy of each class in any derived classes (hence the virtuals to avoid the Dreaded Diamond). Some classes, like D, need to combine all the previously extended classes, retaining all their functions while implementing additional ones.
For added fun I'm (stuck) using C++03, gcc 4.4.6, and make 3.81.
Everything compiles fine, but I keep getting 'undefined reference to '[base class function]' at link whenever and however I attempt to use the base class functions in the derived class.
All the answers I've been able to find so far are about incorrectly implementing pure virtual functions, trying to monkey with constructors, or have failed to implement all the members of a class (hence the vtable errors). I'm not (knowingly) doing or intending any of these things.
It would be cool if these were implemented as templates, but it's unfortunately not possible due to the complexity. I can't post the actual code, but I've mocked up examples resembling the basic structure and behavior:
Header file declaring the classes:
#ifndef CODE_H
#define CODE_H
class A
{
protected:
int a_;
int b_;
int c_;
public:
explicit A() :
a_(0), b_(0), c_(0) {}
A(const int X, const int Y, const int Z) :
a_(X), b_(Y), c_(Z) {}
A(const A& X) :
a_(X.A()), b_(X.B()), c_(X.C()) {}
int doA1(const A& X) const;
int doA2() const;
A getA() const;
A& operator=(const A& X);
const int& A() const {return a_;}
const int& B() const {return b_;}
const int& C() const {return c_;}
//One for each operator but not shown for brevity
A operator+(const A& X) const;
void operator+=(const A& X);
A operator+(const int X) const;
void operator+=(const int X);
};
class B : public virtual A
{
protected:
int d_;
public:
explicit B() :
A(), d_(0) {}
B(const int D, A X) :
A(X), d_(D) {}
B(const int D) :
d_(D) {}
int doB1(const B& X) const;
B getB() const;
B& operator=(const B& X);
const int& D() const {return d_;}
//One for each operator but not shown for brevity.
//int d_ doesn't need to be modified by the operators, so it's ignored in their implementation.
B operator+(const B& X) const {return B(d_, (A::operator+(X.getA())));}
void operator+=(const B& X) {A::operator+=(X.getA());}
B operator+(const int X) const; {return B(d_, (A::operator+(X)));}
void operator+=(const int X) {A::operator+(X);}
};
class C : public virtual A
{
protected:
int e_;
int f_;
int g_;
public:
explicit C() :
A(), e_(0), f_(0), g_(0) {}
C(const int U, const int V, const int W,
const int X, const int Y, const int Z) :
A(U, V, W), e_(X), f_(Y), g_(Z) {}
C(const A& W,
const int X, const int Y, const int Z) :
A(W), e_(X), f_(Y), g_(Z) {}
C(const C& X) :
C(X.A(), X.B(), X.C()), e_(X.E()), f_(X.F()), g_(X.G()) {}
int doC1(const C& X) const;
C getC() const;
C& operator=(const C& X);
const int& E() const {return e_;}
const int& F() const {return f_;}
const int& G() const {return g_;}
//One for each operator but not shown for brevity
C operator+(const C& X) const;
void operator+=(const C& X);
C operator+(const int X) const;
void operator+=(const int X);
};
class D : public virtual B, public virtual C
{
public:
explicit D() :
B(), C() {}
D(const int D, C Y) :
B(D), C(Y) {}
int doD1(const D& X) const;
int doD2() const;
D getD() const;
D& operator=(const D& X);
//One for each operator but not shown for brevity.
D operator+(const D& X) const {return D(d_, (C::operator+(X.getC())));}
void operator+=(const D& X) {C::operator+=(X.getC());}
D operator+(const int X) const; {return D(d_, (C::operator+(X)));}
void operator+=(const int X) {C::operator+(X);}
};
#endif
File implementing A:
#include header.h
int A::doA1(const A& X) const
{
int doStuff;
//does stuff.
return doStuff;
}
int A::doA2() const
{
int doStuff2;
//does stuff.
return doStuff2;
}
A A::getA() const
{
A out(a_, b_, c_);
return out;
}
A& A::operator=(const A& X)
{
if (this != &X)
{
a_ = X.a_;
b_ = X.b_;
c_ = X.c_;
}
return *this;
}
//One for each operator but not shown for brevity
A A::operator+(const A& X) const
{
return A(a_ + X.a_, b_ + X.b_, c_ + X.c_);
}
void A::operator+=(const A& X)
{
a_ += X.a_;
b_ += X.b_;
c_ += X.c_;
}
A A::operator+(const int X) const
{
return A(a_ + X, b_ + X, c_ + X);
}
void A::operator+=(const int X)
{
a_ += X;
b_ += X;
c_ += X;
}
File implementing B:
#include header.h
int B::doB1(const B& X) const
{
//Linker complains on both doA1 and getA, even if I qualify them or remove all the qualifiers
return (A::doA1(X.getA()));
}
B B::getB() const
{
//Also complains here, with or without qualifiers.
B out(d_, A::getA());
return out;
}
B& B::operator=(const B& X)
{
if (this != &X)
{
//Also here, for presumably the same reason.
A::operator=(D.getA());
d_ = X.d_;
}
return *this;
}
I can provide mockups for C and D as well, though they follow the same basic pattern as A and B.
Based on the answers I've seen so far I should, at most, only need to add the base class qualifier to the functions to avoid any accidental name hiding, but that doesn't appear to work. Also strangely: instantiated objects can't seem to find their public functions (like in doB1). Am I just a moron missing something obvious (which I wouldn't be surprised coming from a C background)?
You are defining global functions instead of class methods.
In class A
int doA1(const A& X) const;
int doA2() const;
Implemetation
int A::doA1(const A& X) const
int doA2() const
Thera is no A:: in second case.
I can't understand why a.funct() can be the left operand of the assignment operator even if funct() is not returning a l-value reference.
class A
{
public:
A funct () {A x; return x;}
};
int main ()
{
A a,b; a.funct()=b;
}
In the auto generated methods for the class, there is
A& operator = (const A&);
which make a.funct() = b legal.
To forbid affectation to rvalue, you may, since C++11, write and implement
A& operator = (const A&) &; // Note the last &
so assignation would only work for lvalue.
In the code, funct should return a variable that can be assigned to.
Note that the code in funct is very dangerous too if it were to be returned by reference; the local variable x will go out of scope once the function ends and the variable returned will cause undefined behaviour as its destructor will have been called.
Your assumption is wrong. Your code is perfectly valid.
Try this code:
#include <string>
#include <iostream>
class A
{
std::string m_name;
public:
A(const std::string& name) :m_name(name) {}
A funct() { A x("intern"); return x; }
A& operator=(const A& a)
{
m_name += a.m_name;
return *this;
}
void print() { std::cout << m_name << std::endl; }
};
int main()
{
A a("A"), b("B"); (a.funct() = b).print();//prints "internB"
}
#include <iostream>
using namespace std;
class A
{
public:
A(int a)
{
length = a;
}
~A(){}
friend A operator +(A& var1, A& var2);
A& operator=(A &other);
int length;
};
A operator +(A& var1, A& var2)
{
return A(var1.length + var2.length);
}
A& A::operator=(A &other)
{
length = other.length;
return *this;
}
int main()
{
A a(1);
A b(2);
A c(3);
c = a; // work
c = a + b; // does not work
cout << c.length ;
return 0;
}
In main(), c = a is successfully compiled but "c = a + b" is not.
However, in A& A::operator=(A &other), if I change (A &other) into (A other) then it works.
Can anyone help me with this case?
The simplest fix is to make your assignment overload take it's parameter by const reference.
Then the temporary returned by a + b can be used with it.
A& A::operator=(A const & other)
{
length = other.length;
return *this;
}
You'll probably want to do the same thing with your operator+ so that c = a + a + a; will work as well.
The problem is that operator + returns a temporary object
friend A operator +(A& var1, A& var2);
But a temporary object may not be bound to a non-const reference that is the type of the parameter of the assignment operator.
A& operator=(A &other);
So the compiler issues an error for statement
c = a + b;
You have three possibility.
The first one os to declare the parameter of the copy assignment operator as constant reference
A& operator=(const A &other);
It is the simplest approach.
The second one is to declare a move assignment operator instead of the copy assignment operator. In this case you explicitly need to define also a copy or move constructor. In this case instead of
c = a;
you have to write
c = std::move( a ); // work
For example
#include <iostream>
using namespace std;
class A
{
public:
A(int a)
{
length = a;
}
~A(){}
friend A operator +(A& var1, A& var2);
A& operator=(A &&other);
A( A && ) = default;
int length;
};
A operator +(A& var1, A& var2)
{
return A(var1.length + var2.length);
}
A& A::operator=(A &&other)
{
length = other.length;
return *this;
}
int main()
{
A a(1);
A b(2);
A c(3);
c = std::move( a ); // work
c = a + b; // does not work
cout << c.length ;
return 0;
}
And at last you could have the both operators simultaneously. For example
#include <iostream>
using namespace std;
class A
{
public:
A(int a)
{
length = a;
}
~A(){}
friend A operator +(A& var1, A& var2);
A& operator=(const A &other);
A& operator=(A &&other);
A( const A & ) = default;
int length;
};
A operator +(A& var1, A& var2)
{
return A(var1.length + var2.length);
}
A& A::operator=(const A &other)
{
length = other.length;
return *this;
}
A& A::operator=(A &&other)
{
length = other.length;
return *this;
}
int main()
{
A a(1);
A b(2);
A c(3);
c = a; // work
c = a + b; // does not work
cout << c.length ;
return 0;
}
In this case in statement
c = a; // work
there will be called the copy assignment operator and in statement
c = a + b; // does not work
there will be called the move assignment operator.
Of course you also may have the copy constructor and move constructor simultaneously the same way as the copy assignment operator and the move assignment operator. For your class you could all them define as defaulted.
For example
#include <iostream>
using namespace std;
class A
{
public:
A(int a)
{
length = a;
}
~A(){}
friend A operator +(A& var1, A& var2);
A& operator=(const A &other) = default;
A& operator=(A &&other) = default;
A( const A & ) = default;
A( A && ) = default;
int length;
};
A operator +(A& var1, A& var2)
{
return A(var1.length + var2.length);
}
int main()
{
A a(1);
A b(2);
A c(3);
c = a; // work
c = a + b; // does not work
cout << c.length ;
return 0;
}
I encountered this code but I could not understand the functionality of this code.
It would be a great help if someone could explain it .
struct A{
int i,j;
A(int ii,int jj) : i(ii),j(ii){}
A(const A&a){
}
A& operator =(const A& a){
i=a.i;j=a.j;
}
};
int main()
{
int i;
A a(1,2);
A b(2,3);
A z = (a=b);
cout<<z.i<<" "<<z.j<<endl;
system("pause");
return 0;
}
Explanation:
struct A{
int i,j;//members i and j
A(int ii,int jj) : i(ii),j(ii){} //A constructor. Short form of A(int ii,int jj){i = ii;j = jj;} Original code is wrong too. Should be j(jj) instead of j(ii)
A(const A&a){}//Another constructor. It is missing the assignment
A& operator =(const A& a){
i=a.i;j=a.j;
}//Equal operator overload definition for A = another A. It copies the data from another A and assign to this new one
};
Complete working code:
#include <iostream>
using namespace std;
struct A{
int i,j;
A(int ii,int jj) : i(ii),j(jj){}
A(const A&a){i=a.i;j=a.j;}
A& operator =(const A& a){i=a.i;j=a.j;}
};
int main()
{
int i;
A a(1,2);
A b(2,3);
A z = (a=b);
cout<<z.i<<" "<<z.j<<endl;
return 0;
}
Your problem is this line:
A z = (a=b);
It ends up invoking both your operator= method and your Copy Constructor. When a = b is executed, it uses the operator= method because a already exists and then a reference to a is returned. You're essentially calling a.operator=(b).
When A z = ... is executed, it actually uses the Copy Constructor A(const A&a), not the operator= method because z does not exist yet. Since z is being created by that copy constructor and i and j are never initialized, when you try to print them out, you get whatever junk was located in the memory reserved for i and j.
Another way to view this line:
A z = (a=b);
Is actually like this:
A z(a.operator=(b));
Here's a full example:
int main()
{
A a(1,2);
A b(2,3);
a = b; //calls A& operator=(const A& a)
A z = a; //calls A(const A& a)
}
In conclusion, the fix is to do this:
A(const A& a)
{
i = a.i;
j = a.j;
}
Three mistakes:
1.A(int ii,int jj) : i(ii),j(ii /* jj here? */){}
2.The copy constructor should initialize the members: A(const A&a): i(a.i), j(a.j) {}
3.You should Add return *this in operator=:
A& operator =(const A& a){
i=a.i;j=a.j;
return *this;
}
The OP has asked the operator overloadin part. if we take a as const how can we edit it.
The operator overloading part is:
A& operator =(const A& a){
i=a.i;j=a.j;
}
When you write a=b, you only expect a to change and not b. This is enforced by the const specifier in the function argument definition. This const specifier has nothing to do with whatever appears on the left hand side of the equal sign. It only says that the right hand side of the equal sign will not be modified.
I have this snippet of the code in my header:
class A {
private:
int player;
public:
A(int initPlayer = 0);
A(const A&);
A& operator=(const A&);
~A();
void foo() const;
friend int operator==(const A& i, const A& member) const;
};
implementation of the operator==
int operator==(const A& i, const A& member) const{
if(i.player == member.player){
return 1;
}
return 0;
}
and I need casting for this part of my code:
i - is some int, which my function receives
A *pa1 = new A(a2);
assert(i == *pa1);
I receive an error non-member function, How can I fix it? thanks in advance
Your error is nothing to do with casting or user-defined conversions.
You can't have a const qualification on a function that isn't a member function so this:
int operator==(const A& i, const A& member) const;
should be this:
int operator==(const A& i, const A& member);
Remove the const qualifier from the friend function. Friend functions are not member functions hence the const qualifier is meaningless.
There are two solutions:
Make operator==() a member function, not a friend:
Interface:
class A {
private:
int player;
public:
A(int initPlayer = 0);
A(const A&);
A& operator=(const A&);
~A();
void foo() const;
int operator==(const A& rhv) const;
};
Implementation:
int A::operator==(const A& rhv) const
{
return this->player == rhv.player;
}
If you really want operator==() as a friend function, just remove the const qualifier, as mentioned in the other posts.