assignments operator between father and son - c++

I have the next classes.
in the main I have 2 kinds of assignments operator (A=A and B=B).
I'm trying to get the main working, so I tried:
class A { // assume that this class is abstract
public:
virtual void assignment(const A& num) = 0;
void operator=(const A& num) { assignment(num); }
void func() = 0; // the class is abstract
};
class B: public A {
int i;
public:
void assignment(const B& num) { i = num.i; }
B& operator=(const B& num) { i = num.i; }
void func() { cout << "hello!\n"; }
};
int main()
A* a1 = new B(7); //assume I have it
A* a2 = new B(6); //assume I have it
B b1(2);
B b2(4);
*a1 = *a2; // implement an assignment operator
b1 = b2; // implement an assignment operator
}
but I got some errors that tell me that B is an abstract class and then the copy constructor doesn't work
any help appreciated!

Ok, now I see what the problem is:
void assignment(const B& num) { i = num.i; }
should be:
void assignment(const A& num) { ... }
However, we now have a problem: num which is of type A does not have a member variable i. So we need to ensure that num is actually of class B. The ... part in the above now turns into:
B& b_num = dynamic_cast<B&>(num);
i = num.i;
Note however that dynamic_cast may throw an exception if you are trying to convert some other type to B& than B.

Related

User defined conversion assigned to const ref variable via temporary object

The code below is a simplified version of the actual problem I am facing.
Assume I do not have permission to modify class A (as it is external library), and its already widely used in my existing code base.
The const & assignment from a temporary object (direct constructor) which also return a const & member variable via implicit conversion is not valid in this case.
How do I prevent or make it legal in this case so that the caller gets the correct A value?
class A
{
public:
A() { }
A(int _r, int _g, int _b)
: r(_r), g(_g), b(_b)
{
}
~A(){ }
int GetR() const { return r; }
int GetG() const { return g; }
int GetB() const { return b; }
private:
int r = 0;
int g = 0;
int b = 0;
};
class Foo
{
public:
Foo() : Foo(A()) {}
Foo(int _r, int _g, int _b) : a(A(_r, _g, _b)) {}
explicit Foo(const A& _a) : a(_a) {}
Foo& operator=(const A& a)
{
*this = Foo(a);
return *this;
}
operator A() const { return a; }
operator const A&() const { return a; }
private:
A a;
};
int main()
{
const A& a = Foo(200, 100, 300);
std::cout << a.GetR() << a.GetG() << a.GetB() << endl; // I may not get 200 100 300 here as Foo is already out of scope
return 0;
}
Motivation
Some background on why I am implementing a class as above. The actual purpose of class Foo is to contain 2 different objects, which actually has the same purpose, just different way of storing data internally. For example, let's say class A and class B, which stores RGB value of color in int and floating (normalized) respectively. And as mentioned above, I do not have permission to modify class A, and its already widely used in my code base.
There are tons of function in my code base which takes in const A& and const B& as a function param. So I am trying to unify this 2 classes for a particular case, where I can just pass in Foo in those places and it will work as expected.
You can apply ref-qualified member functions (since C++11), i.e. mark the conversion operator with lvalue-reference, to prevent it being called on temporaries (rvalues).
class Foo
{
public:
... ...
operator A() const { return a; }
operator const A&() const & { return a; }
operator const A&() && = delete;
... ...
};
Then
const A& a = Foo(200, 100, 300); // invalid; invokes deleted operator
const A& a = static_cast<A>(Foo(200, 100, 300)); // fine; invokes operator A()

copy constructor, operator= in a child class

I want to make an operator= and copy constructor, to be called in the inherited class.
For normal objects, it works fine, but when I'm trying to call, for example, operator= with a pointer, it is just copying the object address.
So my question is, how can I call those methods with pointers?
#include <iostream>
// base class
class a {
public:
//constructors
a(): x(0), y(1), z(0){ std::cout << "no parameter constructor A\n"; }
a(int a, int b, int c) :x(a), y(b), z(c){ std::cout << "parameter constructor A\n"; }
a(const a& ob):x(ob.x), y(ob.y), z(ob.z)
{
std::cout << "copy constructor A\n";
}
//operator
a& operator=(const a& obj)
{
if (this != &obj)
{
x = obj.x;
y = obj.y;
z = obj.z;
}
std::cout << "operator = A\n";
return *this;
}
protected:
int x, y, z;
};
//child class
class b : public a
{
public:
//constructors
b() : p(0){ std::cout << "no parameter constructor B\n"; }
b(int X, int Y, int Z, int B) : a(X, Y, Z), p(B) { std::cout << "parameter constructor B\n"; }
b(const b& obj) :p(obj.p), a(obj)
{
std::cout << "copy constructor B\n";
}
//operator =
b& operator=(const b &obj)
{
if (this != &obj)
{
p = obj.p;
&a::operator=(obj);
}
std::cout << "operator = B\n";
return *this;
}
private:
int p;
};
int main()
{
b obj0(4, 8, 16, 32);
b obj1(obj0); // copy constructor
b obj2;
obj2 = obj1; // operator =
std::cout << std::endl << std::endl;
std::cout << "for pointers:\n\n";
a* obj3 = new b(4, 8, 16, 32);
a* obj4(obj3);
obj4 = obj3;
return 0;
}
One of the purposes of using pointers (or references) is to avoid needing to create a copy of the object. Passing a pointer to the object allows the receiver to refer to and manipulate on the original object.
If you wish the pointer to receive a new object, then you would use new.
When dealing with polymorphism as in your example, you would probably need a virtual method that creates a proper clone (sometimes called a deep copy).
class a {
//...
virtual a * clone () const = 0;
};
class b : public a {
//...
b * clone () const {
return new b(*this);
}
};
//...
a *obj4 = obj3->clone();
//...
We leverage that b * is a covariant return type for a *, so that b::clone() can return a b *, but a::clone() can use the b::clone() as an override and still return an a *.

c++ : Whats difference in "catching reference in value" vs "catching value in value" during function return?

What exactly happens at 1 & 2 internally , when we have assigned by return reference?
Class A
{
A& operator= (const A &ax)
{
return *this;
}
}
int main()
{
A a;
A b;
b = a; // -------------- 1
A c = a; // ----------- 2
}
// ---------------------------------------------------------------
What difference will happen in below (assigned returned value)? :
Class A
{
A operator= (const A &ax)
{
return *this;
}
}
int main()
{
A a;
A b;
b = a; // -------------- 3
A c = a; // ----------- 4
}
There is also principal mistake, because operator= made private and code is ill-formed, but this would be corrected by adding public: access modifiers.
operator= is invoked from object stored to b variable, so this variant of assignment should not perform assignment at all.
#include <iostream>
class A
{
public:
float a1;
A& operator= (const A &ax)
{
return *this;
}
};
int main()
{
A a;
a.a1 = 3;
A b;
b.a1 = 5;
b = a; // -------------- 1
std::cout << b.a1; // outputs 5
A c = a;
std::cout << c.a1; // outputs 3
}
The line
A c = a;
is called initialization and doesn't use operator=, instead it uses (generated by compiler) copy constructor, which does a shallow copy of object.
Your mistake is that member operator= meant to assign its argument's value to this. operator= return result of assignment, which can be used for chaining: a=b=c;
A& A::operator= (const A &right)
is equivalent of
A& operator= (A &left, const A &right)

Content of array being rewritten after return

First things first, I have the below class A which at the same time have a nested class B:
// A.h
class A {
public:
class B;
A();
A(const A& a); // Copy constructor
B& operator[](const unsigned int& a) const;
A operator+(const A& a) const;
/*...*/
~A();
private:
/*...*/
unsigned int size;
B* b;
};
and I'm trying to use the overloaded + operator to "add" two A objects by adding the content of both b members of said objects, and assign the result to a third A object.
b is a dinamically allocated array of B objects.
B is a pretty basic class with just some unsigned int
here's the main function:
// main.cpp
int main(int argc, char** argv) {
A a1, a2, result;
a1.read(argv[1]); // Initialize b member with content read from a file
a2.read(argv[2]); // Initialize b member with content read from a file
result = a1 + a2; // Error [3]
getchar();
return 0;
}
The problem is that when trying to make the sum I get what I think are memory errors like: HEAP[main.exe]: Invalid address specified to RtlValidateHeap( 00A50000, 00A59938 )
here's the implementation of class A:
// A.cpp
A::A() : /*...*/, size(0), b(nullptr) {}
// Copy constructor
A::A(const A& a) : /*...*/, size(a.size), b(nullptr) {
b = new B[size]; // [1]
for (unsigned int i = 0; i < size; i++) {
(*this)[i] = a[i];
}
}
A::B& A::operator[](const unsigned int& i) const {
return b[i];
}
A A::operator+(const A& a) const {
if (size != a.size) {
exit(1); // Size must be the same on both operands
}
A tmp(*this); // Call to copy constructor
for (unsigned int i = 0; i < a.size; i++) {
tmp[i] += a[i];
}
return tmp; // Call to copy constructor [2]
}
A::~A() {
if (b != nullptr) {
delete[] b;
}
}
and of class B:
// B.h
class A::B {
public:
B();
B(unsigned char, unsigned char, unsigned char);
B& operator+=(const B& b);
private:
unsigned int a, b, c, d;
};
// B.cpp
A::B::B() : a(0), b(0), c(0), d(0) {}
A::B::B(unsigned char _a, unsigned char _b, unsigned char _c) {
/*...*/
}
A::B& A::B::operator+=(const B& b) {
/*...*/
return *this;
}
I'm using Visual Studio by the way, and when debugging I've observed:
b member of result points to the same address pointed by b in [1] when the copy constructor is called by the return statement in [2], so far so good
Until the return in [2] the content of b is all right, something like: 0x00669968 00 00 ff 00 00 ff 00 00 ..ÿ..ÿ..
After [3] the content of b in [1] and therefore the content of b member of result object becomes something like: 0x00669968 dd dd dd dd dd dd dd dd ÝÝÝÝÝÝÝÝ, I'm guessing is garbage
Note: all include directives and irrelevant sections of code have been ommited
I've been like two days shaking my head trying to figure out what's wrong with no luck so any help is greatly appreciated, thanks in advance.
I check your code and the problem is that you need a custom copy assignment for class A. In your main you have A a1, a2, result;, the default constructor is called for the 3 objects. Then, in the line result = a1 + a2;, the default copy assignment is called.
When you have pointers in your class and allocate the memory using new then you have to worry about copy constructor and copy assignment. Check this post and the rule of three.
I propose you the next code:
class A {
class B {
unsigned a, b, c, d;
public:
B() : a(0), b(0), c(0), d(0) { }
B(unsigned char a_, unsigned char b_, unsigned char c_) : a(a_), b(b_), c(c_), d(0) { }
// Copy constructor.
B& operator=(const B& b_) {
a = b_.a;
b = b_.b;
c = b_.c;
d = b_.d;
return *this;
}
B& operator+=(const B& b_) {
a += b_.a;
b += b_.b;
c += b_.c;
d += b_.d;
return *this;
}
};
unsigned size;
B* b;
public:
A() : size(0) { }
// Copy constructor.
A(const A& a) : size(a.size) {
b = new B[size];
for (unsigned i = 0; i < size; ++i) {
b[i] = a[i];
}
}
// Copy assigment
A& operator=(const A& a) {
clear();
b = new B[size];
for (unsigned i = 0; i < size; ++i) {
b[i] = a[i];
}
return *this;
}
B& operator[](unsigned pos) const {
if (pos > size) {
throw std::out_of_range("Out of range");
}
return b[pos];
}
A operator+(const A& a) const {
A tmp = *this;
if (size != a.size) {
throw std::out_of_range("Diferent sizes");
}
for (unsigned i = 0; i < a.size; ++i) {
tmp[i] += a[i];
}
return tmp;
}
void read(const char* file) {
clear();
size = size_;
b = new B[size];
/*
* Read your file and update b.
*/
}
void clear() {
if (size) {
delete[] b;
size = 0;
}
}
~A() {
clear();
}
};

local classes c-ism

Only first pair of values output on running this program seem correct, the others don't. What is going on?
#include <iostream>
#include <vector>
class a
{
public:
class b
{
public:
a* parent;
void test()
{
std::cout<<parent->value<<std::endl;
}
} b1;
unsigned long value;
a()
{
b1.parent = this;
value = 2;
}
void go()
{
value++;
b1.test();
}
};
int main()
{
{
a a1;
a1.go();
std::cout<<a1.value<<std::endl;
}
std::cout<<std::endl;
{
a a1; a1 = a();
a1.go();
std::cout<<a1.value<<std::endl;
}
std::cout<<std::endl;
{
std::vector<a> a1; a1.push_back(a());
a1.at(0).go();
std::cout<<a1.at(0).value<<std::endl;
}
return 0;
}
You are missing a copy ctor and assignment operator for type 'a'. When copying or assigning objects, you consequently don't properly update their b1.parent. Instead, the b1.parent values point to a different 'a' object than their real parent.
To see this problem in action, use this in your existing code:
void go() {
value++;
std::cout << (this == b1.parent ? "as expected\n" : "uh-oh\n");
b1.test();
}
To fix it, modify class a:
a() : b1 (this), value (2) {} // a change from your default ctor
a(a const &x) : b1 (this), value (x.value) {}
a& operator=(a const &x) {
value = x.value;
return *this;
}
And modify class b (necessarily to use the ctor initializer as I do above):
b(a *parent) : parent (parent) {}