I'm struggled over some code where I don't know how to name it and how to solve it. I tried to reduce the code to the following example (so the example itself won't make sense, but it shows the problematic):
struct MyInterface {
virtual ~MyInterface() {
};
virtual void Output() = 0;
};
class A {
public:
MyInterface *myInterface;
A(MyInterface *myInterface) {
std::cout << "this in A constructor: " << this << std::endl;
this->myInterface = myInterface;
}
void CallA() {
this->myInterface->Output();
}
};
class B : public MyInterface, A {
public:
int v;
B(int v) : A(this) {
std::cout << "this in B constructor: " << this << std::endl;
this->v = v;
}
virtual void Output() override {
std::cout << "Whatever" << std::endl;
}
void CallB() {
std::cout << "this in CallB: " << this << std::endl;
this->CallA();
}
};
class Foo {
public:
B b;
Foo() : b(42) {
b = B(41); //This will make an "invalid" B:
//generates B on the Stack but assign the bytes to Foo.b (which is on the the heap)
//so b.myInterface will point to the stack
//after leaving this context b.other will be invalid
}
void Exec() {
b.CallB();
}
};
int main(int argc, char **args) {
Foo *foo = new Foo();
foo->Exec(); //Gives a segfault, because foo->b.myInterface is not valid
return 0;
}
First I thought it has something to do with the inheritance and its virtual methods. But I think the main problematic is the this pointer within the constructors.
So my questions: When b is constructed, the this pointer in the constructors points to the stack. Why doesn't show the this pointer to the target memory (in the heap)? No copy constructor is called - Why?
How can I Name this problem?
The copy constructor isn't called because you aren't creating a new object you are assigning to an existing object. This calls the assignment operator.
This is copy construction:
B b1(42); // construction
B b2(b1); // copy construction
B b3 = b1; // looks like assignment but is actually copy construction
This is assignment:
B b1(42); // construction
b1 = B(43); // b1 already exists we can't copy construct, construct a new object and assign to b1
You need to override the assignment operator:
class B
{
B& operator=(const B& other)
{
// fix references to this here
}
}
Related
I am working on a system where a class has a private member that is a base class pointer. The pointer can be pointing to an inherited class object. I would like the parameterized and copy constructors to be able to take a pointer of the base class type and deep copy it without erasing the inherited type. Here is some code I made to demonstrate this problem; I would like c2 and c3 to call B.print instead of A.print, but can't figure out how.
#include <iostream>
class A
{
protected:
double a;
double b;
public:
A()
{
a = 0.0;
b = 0.0;
}
A(double a, double b)
{
this->a = a;
this->b = b;
}
A(const A& copy)
{
a = copy.a;
b = copy.b;
}
virtual void print()
{
std::cout << "print A" << std::endl;
std::cout << "a: " << a << ", b: " << b << std::endl;
}
};
class B : public A
{
private:
double c;
public:
B()
{
c = 0.0;
}
B(double a, double b, double c) : A(a, b)
{
this->c = c;
}
B(const B& copy) : A(copy)
{
c = copy.c;
}
virtual void print()
{
std::cout << "print B" << std::endl;
std::cout << "a: " << a << ", b: " << b << ", c: " << c << std::endl;
}
};
class C
{
private:
A* a;
public:
C()
{
a = nullptr;
}
C(A* a)
{
this->a = new A(*a);
}
C(const C& copy)
{
a = nullptr;
if (copy.a != nullptr)
a = new A(*copy.a);
}
~C()
{
delete a;
a = nullptr;
}
void print()
{
if (a != nullptr)
a->print();
}
};
int main()
{
A* a = new A(3.5, 4.5);
A* b = new B(3.5, 4.5, 5.5);
C c1(a), c2(b), c3(c2);
delete a, b;
c1.print();
c2.print();
c3.print();
}
I have tried including an enum of the available types and storing that value separately, but that program was non-extensible as it would require changing a switch and enum for each added inherited type.
Your actual problem is with these lines:
C(A* a) {
this->a = new A(*a);
}
C(const C& copy) {
a = nullptr;
if (copy.a != nullptr)
a = new A(*copy.a);
}
which explicitly create an object with dynamic type A, ignoring the dynamic types of a and copy.a.
The usual pattern for copying something's real dynamic type is
struct Base
{
// copy ctor etc. as usual
virtual Base* clone() const { return new Base(*this); }
};
struct Derived: Base
{
virtual Base* clone() const { return new Derived(*this); }
};
Other, miscellaneous notes:
You don't need to burn 6 lines on a default constructor that does nothing any more. Just write
class A
{
protected:
double a{};
double b{};
and let the compiler default it. You can default most of your copy constructors too.
If you're controlling pointer lifetime (as C is), just use std::unique_ptr. It's there, it's free, it's much more explicit about your semantics.
When you're owning (ie, controlling the lifetime of) a polymorphic object via a base-class pointer, that base class needs to have a virtual destructor (unless you're doing something exotic with a type-erased deleter, which is out of scope here).
If you've decided to use this->a for data members, use it consistently. If you're only using it for disambiguation, just change the parameter/local variable name so it doesn't collide in the first place.
There are member-naming conventions like m_a or just a_ which make it easy to see which variables are data members, remove ambiguity, and are still less typing/visual noise than randomly sprinkling this-> around.
Working code with only the changes described above:
#include <iostream>
#include <memory>
class A
{
protected:
double a_{};
double b_{};
public:
A() = default;
A(double a, double b) : a_(a), b_(b) {}
A(const A&) = default;
virtual ~A() = default;
virtual A* clone() const { return new A(*this); }
virtual void print()
{
std::cout << "print A" << '\n'
<< "a: " << a_ << ", b: " << b_ << '\n';
}
};
class B : public A
{
double c_{};
public:
B() = default;
B(double a, double b, double c) : A(a, b), c_(c) {}
B(const B&) = default;
virtual B* clone() const override { return new B(*this); }
virtual void print() override
{
std::cout << "print B" << '\n'
<< "a: " << a_ << ", b: " << b_ << ", c: " << c_ << '\n';
}
};
// owns and deep-copies an A.
// class invariant: ptr_ is non-null
//
class C
{
private:
std::unique_ptr<A> ptr_;
public:
explicit C(A* a) : ptr_(a->clone()) {}
C(const C& copy) : ptr_(copy.ptr_->clone()) {}
void print()
{
ptr_->print();
}
};
int main()
{
A a{3.5, 4.5};
B b{3.5, 4.5, 5.5};
C c1(&a), c2(&b), c3(c2);
c1.print();
c2.print();
c3.print();
}
NB. The top-level dynamic allocation was unnecessary even if you do want C to deep copy, so I just removed it entirely instead of either changing it to also use unique_ptr or fixing that incorrect delete statement.
I have the following code:
class A {
public:
A() { cout << "A()" << endl; }
void f() { cout << "A" << endl; }
};
class B : public A {
public:
B() { cout << "B()" << endl; }
void f() { cout << "B" << endl; }
void ff() { cout << "ff()" << endl; }
};
int main()
{
A a = B();
B b;
a = b;
}
How calling A a = B(); will be different from A a = A();? Why is the conversion from derived class to base class possible?
When you do A a = B();, copy constructor of class A should be invoked after default constructor of class B has been invoked (Note: Compiler may remove unnecessary copy using copy elison).
A(const A& other)
{
}
Since, object of class B can be passed to copy constructor of class A, it will be allowed but you may experience object-slicing.
If you are curious to know "how is it possible to pass a derived class object to a method accepting a reference to the base class", read the following:
Is it possible to pass derived classes by reference to a function taking base class as a parameter
I'm currently writing a complicated class and in it I basically need to copy a list of derived classes. The simplified version is, as follows:
I have a base class from which I derive several other classes:
class Base
{
public:
virtual void test(void)
{
cout << "Base" << endl;
}
Base(vector<Base*> *pointer)
{
pointer->push_back(this);
}
virtual Base& operator=(const Base& rhs)
{
cout << "Base=" << endl;
return *this;
}
};
class A : public Base
{
public:
void test(void)
{
cout << "A" << endl;
}
A(vector<Base*> *pointer) : Base(pointer) {}
A& operator=(const A& rhs)
{
cout << "A=" << endl;
return *this;
}
};
class B : public Base
{
public:
void test(void)
{
cout << "B" << endl;
}
B(vector<Base*> *pointer) : Base(pointer) {}
B& operator=(const B& rhs)
{
cout << "B=" << endl;
return *this;
}
};
Then I create a list of objects, which I save in the in a pointer list of the Base class:
vector<Base*> listA;
new Base(&listA);
new A(&listA);
new B(&listA);
These objects I then want to copy in a second list with the same classes (same order), but which might have different values.
for (int i = 0; i < (int)listA.size(); i++)
{
(*listA[i]) = (*listB[i]);
}
However c++ is not able to do that. Because the list has the type Base*, dereferencing creates an object of type Base. Therefore the assignment operator= of the Base class is called instead of the correct one from the derived class. How can I fix this?
Or how can I tell c++ to use the right operator? Maybe by some isinstanceof-function?
For a full sample see:
int main()
{
vector<Base*> listA;
new Base(&listA);
new A(&listA);
new B(&listA);
vector<Base*> listB;
new Base(&listB);
new A(&listB);
new B(&listB);
for (int i = 0; i < (int)listA.size(); i++)
{
(*listA[i]).test();
}
for (int i = 0; i < (int)listA.size(); i++)
{
(*listA[i]) = (*listB[i]);
}
}
Which outputs:
Base
A
B
Base=
Base=
Base=
There are a few misunderstandings here. First and foremost, what does it mean to assign an instance of a derived class to an instance of a base class? Let's take a simple hierarchy:
struct A { int x; };
struct B : A { int y; };
A a;
B b;
a = b; // what should this do?
b = a; // what about this?
With normal C++, the first one does object slicing, and the second one is ill-formed. But even the first one, well well-formed, is typically not what you want to do anyway. Are you sure you want to be slicing?
The second is that while you made your assignment operator virtual:
virtual Base& operator=(const Base& rhs)
None of the derived classes actually override it. A's assignment operator takes an A const& and B's takes a B const&. If you marked the two with override, your compiler would point this out to you. If you fix those two to take a Base const& argument, then you would get what you want printed - but it's probably still not what you actually want to have happen.
In order to actually make polymorphic copies, a typical solution is to provide a virtual clone method:
virtual Base* clone() const = 0;
That your derived classes implement:
struct A : Base {
A* clone() const override { return new A(*this); }
};
And then use clone() instead of assignment. There will be no slicing here.
Insert the usual caveats about memory management and raw pointers here.
Okay. I found a solution for my problem. I implemented a copy function which takes the Base class as the argument. Inside this copy function I can copy the variables using the pointa. The classe now are as follows:
class Base
{
public:
virtual void test(void)
{
cout << "Base" << endl;
}
Base(vector<Base*> *pointer)
{
pointer->push_back(this);
}
virtual void clone(Base* pointer) = 0;
};
class A : public Base
{
public:
void test(void)
{
cout << "A" << endl;
}
A(vector<Base*> *pointer) : Base(pointer) {}
void clone(Base* pointer) override
{
A* pointa = (A*)pointer;
cout << "clone A" << endl;
//Clone Variables here
}
};
class B : public Base
{
public:
void test(void)
{
cout << "B" << endl;
}
B(vector<Base*> *pointer) : Base(pointer) {}
void clone(Base* pointer) override
{
B* pointa = (B*)pointer;
cout << "clone B" << endl;
//Clone Variables here
}
};
This means I can now copy the objects in the following way:
for (int i = 0; i < (int)listA.size(); i++)
{
listA[i]->clone(listB[i]);
}
However this solution is not in any way typesafe, a requirement I want to meet. I looked into my idea, and decided to do things manually without the list, which means lot's of duplicated code, but brings peace of mind.
A has a static function A::create() that creates an instance of A, does some initialization, and returns a pointer to it.
I want to create a subclass of A and have a similar create() func:
class B : public A {
public:
static B* create();
int val;
//...
}
in this B::create() function I have to do the following:
B* B::create() {
auto b = (B*)A::create();
b -> val = 0;
//...
return b;
}
Is this the right way to do it? What will happen after the cast?
Follow-up: A has a protected/private constructor, How should I write B::create(), or B's constructor? I do want the vars inherited from A to have the same values as those created by A::create() would have
The cast won't do anything sensible unless A::create() returns a pointer to a B object. If A::create() returns a pointer to an object which isn't a B you have undefined behavior.
In C++ you deal with initialization of objects using constructors: the initialization of base classes is inherited and each derived can do whatever custom initialization it needs to do. Your B::create() would just return a suitably constructed object:
B::B()
: A() // initialize base
, val(0) {
// other initialization
}
B* B::create() { return new B(); }
You could make class B a friend of A like this
class A {
public:
static A* createA();
int varA;
private:
friend class B; // Make B a friend so that B can use private constructor of A
A()
{
cout << "In A constructor" << endl;
varA = 5; // Initialize members of A here
}
};
A* A::createA()
{
return new A;
}
class B : public A {
public:
static B* createB();
int varB;
private:
B()
{
cout << "In B constructor" << endl;
varB = -5; // Initialize members of B here
}
};
B* B::createB()
{
return new B;
}
int main()
{
cout << "Create A" << endl;
A* x=A::createA();
cout << "x->varA is " << x->varA << endl;
cout << endl;
cout << "Create B" << endl;
B* y=B::createB();
cout << "y->varA is " << y->varA << endl;
cout << "y->varB is " << y->varB << endl;
cout << endl;
delete x;
delete y;
}
When a new B is made, the constructor of A get called automatically and the members of A will be initialized.
Output is:
Create A
In A constructor
x->varA is 5
Create B
In A constructor
In B constructor
y->varA is 5
y->varB is -5
Another way is to make the constructor of A protected instead of private.
I'm getting confused why p->a() is calling B::a()?. Is there a paragraph somewhere in the C++ documentation/standard that describes this behavior well?
#include <iostream>
using namespace std;
class A {
public:
A() { cout << "A ctor" << endl; a_instance = this; }
static A *get_instance() { return a_instance; }
static A *a_instance;
void virtual a() { cout << "From base class" << endl; }
};
class B : public A {
public:
B() { cout << "B ctor" << endl; b_instance = this; }
static B *get_instance() { return b_instance; }
static B *b_instance;
void virtual a() { cout << "From derived class" << endl; }
};
A *A::a_instance = 0;
B *B::b_instance = 0;
main()
{
cout << "Create A" << endl;
A ab;
cout << "Create B" << endl;
B abc;
B *ptr = B::get_instance();
A *p = A::get_instance();
cout << "Called from A object type" << endl;
if (p) {
p->a();
}
}
When you create the variable abc, A's constructor sets a_instance to that instance. Despite p being a pointer to an A, since the instance is pointing to a B, it's correctly calling B::a().
To fix this behaviour, you could use the following:
A* A::get_instance()
{
static A a;
return &a;
}
B* B::get_instance()
{
static B b;
return &b;
}
and remove all code that has to do with a_instance and b_instance.
The B constructor calls the A constructor first. That replaces the a_instance that you'd already created.
This chaining of constructors is well defined in the standard. The base is always called first, so that the derived constructor is guaranteed to be working on a valid base object.
What you are experiencing is caused by the design error, which is based on A's constructor initializing the static member using this. Body of this constructor is invoked not only when you are creating the instance of A but also when you are creating the instance of any of its derived classes:
A() { /* ... */ a_instance = this; }
So when you create an instance of type B, before the body of B's constructor is executed, the body of A's constructor is executed at first - this overwrites member a_instance with this within a context of instance of type B, i.e. it makes a_instance to point to this new instance of type B.
What you could do is to place a static variable inside of the getInstance method:
class A
{
public:
static A* getInstance() {
static A s; // <-- instantiated upon first call
return &s;
}
void virtual foo() { std::cout << "From base class" << std::endl; }
protected:
A() { } // <-- protected constructor
~A() { }
A(const A&); // <-- protected copy constructor
A& operator=(const A&); // <-- protected assignment operator
};
then B:
class B : public A
{
public:
static B* getInstance() {
static B s; // <-- instantiated upon first call
return &s;
}
void virtual foo() { std::cout << "From derived class" << std::endl; }
protected:
B() { } // <-- protected constructor
~B() { }
B(const B&); // <-- protected copy constructor
B& operator=(const B&); // <-- protected assignment operator
};
and possible usage:
int main() {
A::getInstance()->foo();
B::getInstance()->foo();
}
that outputs:
From base class
From derived class
B constructor invokes A constructor...