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/
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 a virtual function from the constructor
(3 answers)
Closed 5 years ago.
#include <iostream>
class Base {
public:
virtual void method() {
std::cout << "Base" << std::endl;
}
Base() {
method();
}
};
class Sub : public Base {
public:
virtual void method() {
std::cout << "Sub" << std::endl;
}
Sub() : Base() {
}
};
int main(void) {
Base *b = new Sub();
delete b;
system("PAUSE");
return 0;
}
Output: "Base"
What do i have to change to make the Base call the Sub Method instead of the Base?
This is probably a duplicate and a beginner-question, but i couldn't find an answer to this problem.
Also a suggestion for a better title is welcome as the current one might be wrong.
a) because the standard says so.
b) philosophically, because Sub at this point has not had its constructor called (inherited objects are constructed in a depth-first manner), so calling Subs version of method would surprise the author of Sub.
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.
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.
This question already has answers here:
vector of objects
(5 answers)
Closed 8 years ago.
class classa {
public:
virtual void foo();
};
class classb : public classa {
public:
virtual void foo() override;
};
void classa::foo()
{
std::cout << "foo from a" << std::endl;
}
void classb::foo()
{
std::cout << "foo from b" << std::endl;
}
int main()
{
std::vector<classa> stuff;
classa a;
classb b;
stuff.push_back(a);
stuff.push_back(b);
stuff[0].foo();
stuff[1].foo();
return 0;
}
I expected the above code to return
foo from a
foo from b
but it returns both as foo from a.
I think this is because the vector stores classa but I am not sure.
How can I get classb:foo() to be called by b?
This happens because of object slicing, you'll need to keep a vector of pointers (preferably smart pointers).
I'm assuming stuff is defined as std::vector<classa> stuff;. When you do
stuff.push_back(b);
the object pushed into the vector is a slice of b - particulary the classa part. All other type info is lost. For this to work as expected, you'd need:
std::vector<classa*> stuff;
or similar. The way your code is now, you can't get it to work because stuff[1] is no longer a classb, but a classa.