I have the following program:
#include <iostream>
using namespace std;
class N {
public:
float x;
N(){ x = 3.0; }
N(float y){ x = y; }
N &operator=(float f){ return *new N(f); }
};
int main(){
N a;
a = 2.0;
cout << a.x;
return 0;
}
I am expecting for the result to be 2 (because of definition of operator=), but instead it gives me 3 (like there is no line a = 2.0). Can someone, please, explain me why is this happening, what is wrong with definition of 'operator='? Thank you...
Your copy assignment operator should be setting the value of x, then returning a reference to *this, like so:
N &operator =(float f) { x = f; return *this; }
Instead, your copy assignment operator is constructing a new instance of N on the heap, and returning a reference to that.
You shouldn't use new, C++ isn't java.
N& operator=(float f)
{
x = f;
return *this;
}
Try this.
Related
Yes I know it sounds weird, but I'm looking for a way to overwrite the indirection operator to return another class object. Let me explain better:
In main.cpp I got
MyInt *V = new MyInt[10];
(*V)[3]=10;
but I would like to have it like:
MyInt *V = new MyInt[10];
V[3]=10;
In MyInt.h I've used a wrapper to catch and remove the square brackets of MyInt class and then overload the "=" operator. That's because I need a class that could store the vector and also a counter of its usage inside it. More details here.
MyInt.h
wrapper operator[] ( std::size_t i ) { return wrapper( *this, i ) ; }
The work flow is "MyInt::wrapper::operator=".
Now it works but I would like to get rid of (*V). Would be possible to remove it by overloading the indirection operator to return a wrapper object that could be passed to "wrapper::operator=" then?
I was thinking something like:
MyInt& operator*(){
return wrapper(*this)
}
but it doesn't work, I get "error: invalid initialization of non-const reference of type ‘MyInt&’ from an rvalue of type ‘test::wrapper’". I know that the indirection operator should return the same class, but I really need it that way. Any suggestion? Thanks in advance.
Note: This answer was written when OPs question was:
I would like to have it like:
MyInt V = new MyInt[10];
V[3]=10;
I'll leave this answer up in case anyone is interested in a solution for that.
#include <cstddef>
class MyInt {
public:
MyInt() = default;
MyInt(MyInt* d) : data(d) {} // constructor taking a `MyInt*`
// ... rule of 5 implementation needed here ...
MyInt& operator[](size_t idx) { return data[idx]; }
MyInt& operator=(int) { return *this; }
private:
MyInt* data = nullptr;
};
int main() {
MyInt V = new MyInt[10];
V[3]=10;
}
Note that there's no way for V to know how many elements data is pointing at.
Following the link to your earlier question, and the requirements you've added there, V[3] is undefined behaviour.
You have changed the meaning of new [] to return a pointer to a single object.
You need to completely rethink your design, such that there are 10 MyInt objects for V to point to.
struct MyCounts
{
int num_read = 0;
int num_write = 0;
};
class MyInt
{
int value;
MyCounts * counts;
static void* operator new[](size_t n){
void * ptr = malloc(sizeof(MyCounts) + n * sizeof(MyInt));
MyCounts * counts = new (ptr) MyCounts;
ptr = static_cast<void *>(counts + 1);
for (size_t i = 0; i < n; ++i, ptr += sizeof(MyInt)) {
new (ptr) MyInt{ counts };
}
return static_cast<void *>(counts + 1);
}
static void* operator delete[](void* ptr, size_t n){
for (MyInt * last = reinterpret_cast<MyInt *>(ptr) + n; --last != ptr; ) {
last->~MyInt();
}
ptr -= sizeof(MyCounts);
reinterpret_cast<MyCounts *>(ptr)->~MyCounts();
free(ptr);
}
public:
MyInt& operator=(int i) { value = i; ++counts->num_write; return *this; }
operator int() const { ++counts->num_read; return value; }
};
I would like to have it like:
MyInt* V = new MyInt[10];
V[3]=10;
You need MyInt to implement an operator= taking an int to "write" to it, and a conversion oeprator to "read" from it:
#include <iostream>
struct MyInt
{
int value;
MyInt& operator=(int v) { value = v; return *this; }
operator int() const { return value; };
};
int main()
{
MyInt *V = new MyInt[10];
V[3]=10;
std::cout << V[3] << '\n';
}
I have a class MyFloat:
class MyFloat
{
public:
float value = 0.0;
}
I use it so far in this way:
MyFloat *myfloat1 = new MyFloat;
myfloat1->value = 1.0;
How can I make
myfloat1 = 2.0;
if (myfloat1 < 3.0){
...
}
You can use operator= and operator float
class MyFloat
{
public:
float value = 0.0;
MyFloat& operator=(float f)
{
value = f;
return *this;
}
operator float() const
{
return value;
}
};
int main() {
MyFloat f;
f = 10.0f;
float x;
x = f;
return 0;
}
As others have mentiond you could provide a operator=(float), however for a MyFloat it is more natural to be constructed with a float instead of first constructing it and then assigning a value:
class MyFloat {
public:
float value = 0.0;
MyFloat(float x) : value(x) {}
MyFloat() {}
};
int main() {
MyFloat x;
x = 1.0; // works because MyFloat(float) is used
MyFloat y(2.0); // this is nicer
}
PS: as pointed out by R2RT, for x = 1.0; you dont want to use the constructor, but an assignment operator (I just left the line because thats what you were asking for). However, for a newly constructed MyFloat I would always prefer to pass the value to the constructor.
Your object is of type MyFloat, not float so you can't assign a float value to it. What you can do is assign a float value to a data member of your class by overriding the class' = assignment operator:
MyFloat& operator=(float p) {
value = p;
return *this;
}
I was studying C++, and when I made a little program to learn more about Operator Overloading the program gives an erro in the main function where I wrote "Ponto p1(1,5), p2(3,4), Soma;". Can anyone explain me how to use Operator Overloagin correctly? Thank you.
PS: The program is in Portugueses, my native language, but I think that it will not be a problem to find my erro.
#include <iostream>
using namespace std;
class Ponto
{
private:
int x,y;
public:
Ponto(int a, int b)
{
x = a;
y = b;
}
Ponto operator+(Ponto p);
};
Ponto Ponto::operator+(Ponto p)
{
int a, b;
a = x + p.x;
b = y + p.y;
return Ponto(a, b);
}
int main(void)
{
Ponto p1(1,5), p2(3,4), Soma;
Soma = p1.operator+(p2);
return 0;
}
You don't have a default constructor so when it tries to construct Soma you get an error.
Once you provide your own constructor the default one provided by the compiler is no longer generated. You either have to make your own or add default values to the parameters on the constructor that takes parameters.
You should init Ponto Some in place with some value: Ponto Some = p1 + p2;
Also you should pass "constant reference" - reference to const object: const Ponto &name into the operator+.
So, fixed code:
#include <iostream>
using namespace std;
class Ponto {
int x, y;
public:
Ponto(int, int);
Ponto operator+(const Ponto&);
};
Ponto::Ponto(int a, int b) : x(a), y(b) {}; // Use 'initializer list'
Ponto Ponto::operator+(const Ponto &other) {
// Not need to do calculations explicitly
return Ponto(x+other.x, y+other.y);
}
int main() {
Ponto p1(1, 5), p2(3, 4);
// Not need to call operator+ explicitly - it's compiler's work
Ponto Soma = p1 + p2;
return 0;
}
In the below code snippet
#include <iostream>
class A
{
public:
A(int i) : m_i(i) { }
public:
int operator()(int i = 0) const
{
return m_i + i;
}
operator int () const
{
return m_i;
}
operator float () const
{
return 0.0;
}
private:
int m_i;
friend int g(const A&);
};
int f(char c)
{
return c;
}
int g(const A& a)
{
return a.m_i;
}
int main()
{
A f(2), g(3);
int i = f;// call 1
std::cout << f(1) << g(f) << std::endl;// call 2
return 0;
}
I gave some comments like call 1 and call 2 in the main function.
I understood why operator int is called at call 1.
But I could not understand why at // call 2
Can some body explain me why it is so.
The function g is hidden by the g (of type A) in scope. So g(f) converts f to int then calls g.operator()(int) with the result of the conversion.
When you call g(f), A::operator()(int i=0) is called for g.
f must therefore be converted into an int, which is done via A::operator int() .
std::cout << f(1) << g(f) << std::endl;
Let's break this down into function calls instead of operators. (This might not be technically correct syntax.)
int temp1 = f.operator()(1);
ostream& temp2 = std::cout.operator<<(temp1);
// By the implementation of ostream::operator<<, temp2 is a reference to std::cout.
// The compiler doesn't know this, though, and must treat it as if it could be different.
int temp3 = f.operator int(); // Typecast since A::operator() expects an `int`.
int temp4 = g.operator()(temp3);
ostream& temp5 = temp2.operator<<(temp4);
// temp5 is another reference to std::cout.
temp5.operator<<(std::endl);
// Result discarded.
Right now, I must write
st[1];
st = 5;
What must I change in my code to be able to do this:
st[1] = 5;
#include <iostream>
using namespace std;
class A
{
public:
A(){this->z = 0;}
void operator = (int t) { this->x[this->z] = t+10; }
int& operator [] (int t) { this->z=t; return this->x[t]; }
private:
int x[2];
int z;
};
void main()
{
A st;
st[0]=9;
cout<<st[0];
system("pause");
}
UPD: Now I see 9 instead 19.
The built-in operator = expects an lvalue as its left hand operand. Therefore, in order for this statement to compile:
st[1] = 5;
You need to change the return type of your operator [] from int to int&:
int& operator [] (int t) { return this->x[t]; }
// ^^^^
You could also provide a const overload, which will return a reference to const if the object on which operator [] is invoked is const:
int const& operator [] (int t) const { return this->x[t]; }
// ^^^^^^^^^^ ^^^^^