This question already has answers here:
What is object slicing?
(18 answers)
Closed 8 years ago.
Consider the following code:
class A {
public:
virtual void hello() { std::cout << "Hello from A" << std::endl; }
void hi() { std::cout << "Hi from A" << std::endl; }
};
class B : public A {
public:
void hello() { std::cout << "Hello from B" << std::endl; }
void hi() { std::cout << "Hi from B" << std::endl; }
};
int main() {
A foo = B();
foo.hello(); // prints "Hello from A"
foo.hi(); // prints "Hi from A";
A *bar = new B();
bar->hello(); // prints "Hello from B"
bar->hi(); // prints "Hi from A"
}
I'm aware that since hello() is declared as a virtual function in class A, any object of class B should have overridden behavior. However, why doesn't the object foo call the overridden hello()?
In other words, in what ways are the two object construction methods different? A foo = B(); v/s A *bar = new B()?
Thanks!
In the first case you're doing something wrong: slicing which is "cutting away part of the object" since you're assigning a derived object to a base object. You're not using virtual polymorphism because you're just calling methods on a "sliced" derived object (which isn't even safe).
Virtual polymorphism works with base class pointers to derived objects and virtual functions overriding, and that is a safe, runtime, mechanism to specialize your objects and call the appropriate methods.
Related
This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 4 years ago.
I have been debugging an issue involving an std::function (created from std::bind) where the issue boils down to a more fundamental question.
An example follows below, but in short it's about the case when a class in one way or another stores a pointer to itself (or an instance variable) in its constructor and the class itself is then reassigned. From my experiments it seems the stored pointer will then no longer point to the class (or its instance variable). I wonder what are the best practices to avoid these issues?
An example:
#include <iostream>
class Interface
{
public:
Interface() {};
virtual ~Interface() {};
virtual void callback() = 0;
};
class B
{
public:
B() : interface(NULL) {};
virtual ~B() {};
void set_interface(Interface* interface)
{
this->interface = interface;
}
void print()
{
std::cout << "B is at: " << this << std::endl;
std::cout << " Interface (A) from B is at: " << interface << std::endl;
}
private:
Interface* interface;
};
class A : public Interface
{
public:
A()
{
b.set_interface(this);
};
virtual ~A() {};
virtual void callback()
{
std::cout << "Callback" << std::endl;
}
void print()
{
std::cout << "A is at: " << this << std::endl;
b.print();
}
private:
B b;
};
int main(int argc, char** argv)
{
A a;
a.print();
std::cout << "------" << std::endl;
a = A();
a.print();
return 0;
}
When I run this on my machine I get:
A is at: 0x7ffdb8910af0
B is at: 0x7ffdb8910af8
Interface (A) from B is at: 0x7ffdb8910af0
------
A is at: 0x7ffdb8910af0
B is at: 0x7ffdb8910af8
Interface (A) from B is at: 0x7ffdb8910b10
So, at first everything is fine. The pointer to Interface from B points to the address of A. However, after reassigning (a=A()) the pointer to Interface no longer points to A! I realize this is because as the constructor of A is running to create the second instance, it is in a new memory location and stores the interface pointer to this new memory location. When a is then reassigned the object is moved in to the old location which invalidates the pointer to Interface.
This seems like a common use case to me. Should one always avoid referencing memory in constructors of objects?
In my case I would like to bind a callback function and pass it to a class member, it seems I cannot do it in the constructor then and must do it at a later time?
A is at fault:
A()
{
b.set_interface(this);
};
You define a constructor for A which handles a resource: itself. According to the rule of 0/3/5, A should have a user-defined copy constructor and an assignment operator, and if it makes sense, their move conterparts.
A()
{
b.set_interface(this);
};
A(A const&)
{
b.set_interface(this);
}
A& operator=(A const&)
{
b.set_interface(this);
return *this;
}
This question already has answers here:
Calling virtual method from destructor - workaround?
(4 answers)
Closed 5 years ago.
I want to destruct an object of class B.
class A {
public:
A() {
std::cout << "construct A" << av::endl;
a = new int;
}
virtual ~A() {
std::cout << "destruct A" << av::endl;
this->clear();
}
virtual void clear() {
std::cout << "clear A" << av::endl;
delete a;
}
protected:
int *a;
};
class B : public A {
public:
B() {
std::cout << "construct B" << av::endl;
b = new int;
}
~B() {
std::cout << "destruct B" << av::endl;
}
void clear() override {
std::cout << "clear B" << av::endl;
delete b;
delete this->a;
}
private:
int *b;
};
And I want it to be done with clear() method. But when I execute following code:
A *a = new B();
delete a;
I get:
construct A construct B destruct B destruct A clear A
And clear B is never printed.
What am I doing wrong?
Informally, In ~A(); the B part is already destroyed, calling any function of B doesn't make any sense.
Effective C++ Item 9: Never call virtual functions during construction or destruction.
Once a derived class destructor has run, the object’s derived class
data members assume undefined values, so C++ treats them as if they no
longer exist. Upon entry to the base class destructor, the object
becomes a base class object, and all parts of C++ — virtual functions,
dynamic_cast s, etc., —treat it that way.
I didn't know what to give as a title, I expect more experienced stackoverflow.com users to improve it.
Let's say we have the class A
class A {
void hello(){ cout << "i'm an A" << endl; }
}
and its sub-class B
class B: public A {
void hello(){ cout << "i'm a B" << endl; }
}
Then we did somewhere in our program
A* array[2];
array[0] = new A;
array[1] = new B;
array[0]->hello(); // output: "i'm an A"
array[1]->hello(); // output: "i'm a B"
why doesn't the array[1].hello(); output I'm a B since we instanciated a B object for that base-class pointer ? and how to make it happen ?
Couple of changes here:
make function hello in class A, a virtual and public: because by default it is private
class A {
public:
virtual void hello(){ cout << "i'm an A" << endl; }
};
Similarly make hello in class B virtual
class B: public A {
virtual void hello(){ cout << "i'm a B" << endl; }
};
You have to make hello a virtual function:
class A {
virtual void hello() { cout << "i'm an A" << endl; }
};
class B : public A {
virtual void hello() override { cout << "i'm a B" << endl; } // 1)
};
This tells the compiler that the actual function should not be determined by the static type (the type of the pointer or reference) but by the dynamic (run-time) type of the object.
1) The overridekeyword tells the compiler to check, if the function actually overrides a hello function in the base class (helps e.g. to catch spelling mistakes or differences in the parameter types).
Since you have inherited class A in class B, derived class B will call the function from the Base class. You need to override the function in class B, as you want to change the Base class functionality.
You can do this with the override and virtual keywords.
http://en.cppreference.com/w/cpp/language/override
This question already has answers here:
typeid for polymorphic types
(1 answer)
typeid for polymorphic pointers?
(2 answers)
Closed 7 years ago.
Basically what I am wondering is why typeid does not return the typeinfo of the derived type if given a pointer to the derived type.
Example:
If having:
class Base {
public:
virtual void foo() {
std::cout << "This is base speaking" << std::endl;
}
};
class Derived : public Base {
public:
void foo() override {
std::cout << "This is derived speaking" << std::endl;
}
};
The following:
Derived obj;
Base& ref = obj;
Base* ptr = &obj;
std::cout << typeid(obj).name() << std::endl;
std::cout << typeid(ref).name() << std::endl;
std::cout << typeid(ptr).name() << std::endl;
Would result in:
7Derived
7Derived
P4Base
While this:
obj.foo();
ref.foo();
ptr->foo();
Would result in:
This is derived speaking
This is derived speaking
This is derived speaking
My guess would be Base* is a type in itself, namely pointer to Base which is not polymorphic and hence statically determined. The reason why the call to foo results in the derived version is because of the dereferencing (->). Even if I'm right, I still find it somewhat confusing, since the object pointed to by ptr is actually Derived.
This question already has answers here:
What is object slicing?
(18 answers)
Closed 9 years ago.
I have the following piece of code (#includes and using namespace std omitted):
class A {
public:
void call(){callme();}
private:
virtual void callme() {cout << "I'm A" << endl;}
};
class B : public A {
private:
virtual void callme() {cout << "I'm B" << endl;}
};
class C : public B {
public:
virtual void callme(){ cout << "I'm C" << endl;}
};
int main(){
vector<A> stuff = {
A(), B(), C(),
};
stuff[0].call(); // output: I'm A
stuff[1].call(); // output: I'm A
stuff[2].call(); // output: I'm A
return 0;
}
As stated in the comments, the output of the above program is:
I'm A
I'm A
I'm A
However, I would like that C++ automatically recognizes the type with which the corresponding element was created. I.e. I would like that C++ outputs
I'm A
I'm B
I'm C
(That is, the compiler shall pick the proper subclass for me.)
Is this possible in this scenario (i.e. if all the elements come out of a vector)?
Member functions virtuality works only when you call them from pointer to the actual object, not from an object itself, because in your example objects were automatically statically upcasted to class A. Change your code to:
std::vector<std::unique_ptr<A>> stuff = {
std::unique_ptr<A>(new A()),
std::unique_ptr<A>(new B()),
std::unique_ptr<A>(new C()),
};
stuff[0]->call();
stuff[1]->call();
stuff[2]->call();
For C++ Polymorphism, you should use either pointer or reference. You could do like this
int main(){
vector<A*> stuff;
stuff.push_back(new A);
stuff.push_back(new B);
stuff.push_back(new C);
stuff[0]->call(); // output: I'm A
stuff[1]->call(); // output: I'm A
stuff[2]->call(); // output: I'm A
while (!stuff.empty()){
delete stuff.back();
stuff.pop_back();
}
return 0;
}
Reference: http://www.cplusplus.com/doc/tutorial/polymorphism/