Overiding inherited functions - c++

I have a class Object and some derived classes, eg class Bird : public Object. The functions Object::Render and Bird::Render are defined and implemented. (as a matter of fact, Bird::Render calls Object::Render)
I also have a vector<Object*> which is holding a bunch of Bird*s. Now, in the future, this vector will also hold other types of objects.
My question is: without knowing the type of an element of that vector, is it possible to execute its specific Render function, ie can
vector<Object*> objects;
object.push_back(new Bird());
// ...
objects[i]->Render(); // This should execute Bird::Render
As far as I can see, the last line only executes Object::Render (which makes sense, as to the calling function, this is a vanilla Object).
Is there any way to change that?

Object::Render should be virtual function and Bird should override Render function.
class Object
{
public:
virtual ~Object() {}
virtual void Render() = 0;
};
void Object::Render() {}
class Bird : public Object
{
public:
void Render() { Object::Render(); }
};
vector<Object*> objects;
objects.push_back(new Bird());
objects[0]->Render();

Related

Calling overridden methods from a vector of superclass pointers

I am currently writing a small game in OpenGL using C++. Coming from a non-C++ background, I have a simple question about overriding methods and how to call them using a pointer of a superclass type.
This is the case: I have a class Polygon containing the method void draw(). This class has two children called Rectangle and Circle, which both override the drawing method, as I am using different OpenGL calls depending on the type of polygon being drawn.
Now consider this: I wish to store all polygons (including both rectangles and circles) in an std::vector<Polygon*>. This is perfectly fine. However, iterating through the vector and calling draw automatically resorts to the superclass' version of the method.
How can I make a vector of type superclass-pointer, store pointers to subclass objects in it, and call overridden functions depending on the actual type of the object being used?
You are describing polymorphism (or a lack thereof in your current implementation).
To make your draw function polymorphic, you must declare it virtual. See below for an example:
class Polygon {
public:
virtual ~Polygon() {}
virtual void draw() = 0;
};
class Rectangle : public Polygon
{
public:
void draw() override { std::cout << "Rectangle::draw()\n"; }
};
class Circle : public Polygon
{
public:
void draw() override { std::cout << "Circle::draw()\n"; }
};
Note three extra things in the above:
I also declared the destructor virtual. This allows for proper destruction of an object through its base class pointer.
I declared the base draw method as pure-virtual (the = 0 part). This means the Polygon class is abstract and cannot itself be instantiated. You may not want that, but to me it seems there's no use for a draw method on a base class anyway. Define one if you want. Up to you.
The override specifier is optional, but recommended (language feature introduced by C++11). It instructs the compiler that you're intentionally overriding a virtual method, and so if no such method exists to be overridden then it will generate a compiler error.
You need to define the function as virtual in the base class and the override it in the subclasses. For example
#include <vector>
#include <iostream>
struct A{
virtual void p(){std::cout<<"A ";}
A(){}
virtual ~A() {};
};
struct B: public A{
void p()override{std::cout<<"B ";}
B(): A(){}
};
struct C: public A{
void p()override{std::cout<<"C ";}
C() : A(){}
};
int main()
{
A* a=new A();
B* b=new B();
C* c=new C();
std::vector<A*> v={a,b,c};
for(auto i : v)
i->p();
std::cout<<"\n";
delete a;
delete b;
delete c;
return 0;
}
prints "A B C".

C++ base method called instead of derived method

So, I know something like this is asked a lot, but the other answers seem to indicate that this should work, so I thought I'd ask about my code specifically. I spend more time in .NET and Java, so maybe I'm forgetting something.
I'm creating a base widget and a set of specific widgets (buttons, other graphical items). I'm trying to loop through a linked list of widgets and what I would like is for the specific rendering method for that specific widget to be called. Below is simplified code that demonstrates my problem, on my first call to Render, the specific render function is called. If I pass a cGeneralWidget pointer to a function which calls the Render object, the base method was called. I thought, as long as I send a pointer, C++ is smart enough to know what the object really is and call the overridden method.
Otherwise, whats the correct way to deal with a collection of base objects and call the derived methods as appropriate?
Thank you.
class cGeneralWidget
{
public:
void Render()
{
int a = 99;
}
};
class cSpecificWidget : public cGeneralWidget
{
public:
void Render()
{
int a = 99;
}
};
void GeneralRenderingFunction(cGeneralWidget * b)
{
b->Render(); // <-- calls the base function
}
int main(int argc, char* argv[])
{
cSpecificWidget wd;
wd.Render(); // <-- calls the derived function
GeneralRenderingFunction(&wd);
return 0;
}
You should define Render() method in your base class with virtual keyword and in your derived class with override keyword. If you don't put virtual keyword in your base class implementation then C++ wouldn't mark it as virtual.
class cGeneralWidget
{
public:
virtual void Render()
{
int a = 99;
}
};
class cSpecificWidget : public cGeneralWidget
{
public:
void Render() override
{
int a = 99;
}
};
in your base class
class cGeneralWidget
{
public:
virtual void Render()
{
int a = 99;
}
};
Render has to be virtual so it overrides it
Note : A virtual function a member function which is declared within base class and is re-defined (Overriden) by derived class. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class’s version of the function.

Two classes with one class having a pointer to another class

(C++) Suppose I have two classes A and B. Class B has a pointer to class A along with a method. How exactly do I interpret what's going on in this case. When that method is called does it have access to the methods in Class A since it's pointing to a possible instance of A
Class A {
public:
void method1() const;
void method2() const;
}
Class B {
public:
A* method3(int);
void method4();
void method5();
}
Let me know if I'm being vague here or need to provide more info
Edit 1: So basically Class B creates objects that get stored in a map that is accessible by an integer key. Class A has methods that can manipulate any one of those individual objects. So I guess in this case method3() would take in the key of the map as input and then it fetches that object from the map and then the user can choose to do method1 or method2 from Class A to manipulate it.
i.e. The object being stored in the map could be like a game piece and the methods in Class A can like flip it or rotate it.
Why don't you just try it?
class A {
public:
void method1() const;
void method2() const;
}
class B {
public:
A *GetA(int i) { return &mapA[i];
void method3();
private:
std::map<int, A> mapA;
}
int main()
{
B b;
auto pA = b.Get(1);
pA->method1();
return 0;
}
As long as A has a default constructor, this should create new items in B's map if they don't exist.
Note that making class A method1 and method2 const means that they don't change anything in A, so they couldn't be functions which change any of A's state.
The member function A* method3(int) is going to return a pointer to an instance of the class A. Thus the compiler will reserve a proper amount of memory for it on the heap. Most probably you will need to create dynamically an instance of that class inside the function method3 and return the pointer pointing to it.

Calling subclass methods from superclass in a vector C++

I am trying to add a number of subclassed elements into a vector, iterate through them calling a overridden method and want it to call the overridden method where possible. However I have found that it appears to only be calling the superclass method.
I learnt Java and am unsure why it is doing this in C++. I have tried rewriting the code using a vector of pointers of the superclass and casting the pointer of the subclass to the superclass. Accessing this through pointers then works.
Ideally I dont want to have to put a list of pointers into the vector since then I have to manually delete each one (I believe?) to stop memory leaks since I will be creating the objects with new so they persist past the method call to add them into the vector.
Is there a better way to do this or am I stuck to using pointers and calling delete on the created objects when the parent class is unneeded? Preferably the vector would be a list of class X rather than a list of pointers of class X
My structure is:
class a { vector vec of class X,
method to create and add an instance of X into vector vec,
method to create and add an instance of Y into vector vec }
class X { talk() }
class Y : public X { talk() }
Code to demonstrate what I ideally want to do, but showing its broken by only calling the superclass method:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <vector>
class A {
public:
virtual void talk() { printf("A\n"); }
};
class B: public A {
public:
void talk() { printf("B\n"); }
};
int main(void) {
std::vector<A> vec;
std::vector<A*> vec2;
A a;
B b;
a.talk();
b.talk();
vec.push_back(a);
vec.push_back(b);
vec2.push_back(&a);
vec2.push_back(&b);
for(int i = 0; i < vec.size(); i++) {
vec[i].talk();
vec2[i]->talk(); //bad but short for example
}
}
To get the polymorphic behaviour you want you need to add the virtual specifier to the functions in the base class that you want to override in derived classes.
class A {
public:
virtual void talk() { printf("A\n"); }
};
You should also make a habit of adding the override specifier on overridden functions in derived classes so that the compiler can help you with these kind of issues.
class B: public A {
public:
virtual void talk() override { printf("B\n"); }
// ^ Compiler will report an error if base class' function
// is not virtual.
};
Also you can not assign a derived object to an instance of a base class, or slicing will occur.
std::vector<A> vec;
/* ... */
B b;
/* ... */
vec.push_back(b); // Slicing. Information only in B is lost.
Live example using virtual specifier
Live example without virtual specifier
You should declare the methods as virtual in order to be able to override them in a subclass. Also it's good practice to make the destructor virtual.
class A {
public:
virtual void talk() { printf("A\n"); }
virtual ~A(){}
};
class B: public A {
public:
// using virtual is not really necessary here, but it's good for clarity.
virtual void talk() { printf("B\n"); }
};
The method should be virtual.
In java methods are virtual by default.
class A {
public:
virtual void talk() { printf("A\n"); }
};
class B: public A {
public:
virtual void talk() override { printf("B\n"); } //override key word is in C++ 0x and above
};
I think what you are missing is the virtual keyword in your method declaration. If you want to get to a subclass method when invoking methods in a parent class, the methods have to be declared virtual.
If you don't use a pointer you will get 'object slicing' when you copy the object into the vector. This reduces the object to the base type declared in the vector template argument. So there is no subclass, so no subclass method to call, even if the method is virtual.

Create a vector of sub classes?

I have been using a dynamic array but I had to add and remove items. I've read it's not recommended to use realloc or to resize the arrays when one can simply use std::vector however I'm having problems in changing my array to a vector.
This is my current code:
int main(){
// This is what I'm doing now
State*arr[3];
int pos = 0;
arr[0] = new Menu();
// How do I change it to a vector? This is what I'm trying:
std::vector<State> vec;
vec.push_back(Menu());
...
}
However I keep getting error: "Cannot allocate an object of abstract type 'State'" What am I doing wrong?
These are class State and Menu:
class State
{
public:
virtual ~State() {};
virtual void capture_events() = 0;
virtual void logic() = 0;
virtual void render() = 0;
};
Menu : public State
{
public:
Menu();
~Menu();
void capture_events();
void logic();
void render();
};
You need extra indirection because State is a polymorphic base class. You can do this using std::unique_ptr from <memory>.
#include <memory>
std::vector<std::unique_ptr<State>> states;
states.emplace_back(new Menu());
It is very important to use std::unique_ptr<State> and not State*, because of exception safety. Consider the following:
std::vector<State*> states;
states.push_back(new Menu());
foo(); // what if foo throws an exception?
// the next line wouldn’t get executed!
for (auto ptr : states) delete ptr;
In contrast, std::unique_ptr uses RAII to make sure the objects are always deleted if the vector goes out of scope, even in the case of early returns or exceptions. For further reference, see The Definitive C++ Book Guide and List.
You cannot instantiate a class which has pure virtual methods, i.e. a method like
virtual void func() = 0;
The =0means that you must derive the class and implement this method there. This derived class can be instantiated.
As long as a class contains pure virtual methods you cannot instantiate it and you will get your error.
If you use a vector you objects must be default constructible. You can not construct a object of your class State if one of the virtual methods is marked with =0 to set the class abstract. The idea to have a abstract class is that you can't create objects of that class.
What you maybe want to do:
Create a class family with a abstract base like your State. Create a vector of pointers to instances( objects) of your class. Create the objects with new and push_back the pointer to your vector. If you erase some elements don't forget to delete the objects with delete.
Don't forget to make the destructor of your family also virtual!
Something like that:
class Base
{
virtual void Do() =0;
virtual ~Base();
};
class A: public Base
{
void Do() { ... }
}
class B ...
class C ...
// Create your vector somewhere...
vector<Base*> myVect;
void AddObject()
{
// It is not important which kind of object you create. Base* obj can "hold" every
// object which is build from a class which is derived from Base!
Base* obj=new A();
myVect.push_back(obj);
}
void DeleteObj( Base* obj )
{
myVect.erase( ...find the object...);
delete obj;
}
void PopBack()
{
Base* ptr = myVect.back(); // get last object pointer
delete ptr; // delete the object
myVect.pop_back(); // remove pointer to object from vector
}