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
}
Related
I have a simple container class that points to an abstract class and I have functions to get/set the pointer in the container class. More concretely, the class looks like this:
class Container
{
Abstract* thing;
public:
void set(Abstract &obj)
{
thing = &obj; //danger of dangling pointer
}
Abstract* get()
{
return thing;
}
};
Abstract is an abstract class. As can be seen already, there's a danger of a dangling pointer. I know that I could make a copy of the object (new) and then point to it. But I can't create an instance of an abstract class. What solutions to this are there?
The following are just more information:
Class definitions
class Abstract
{
public:
virtual void something() = 0;
};
class Base : public Abstract
{
int a;
public:
Base() {}
Base(int a) : a(a){}
virtual void something()
{
cout << "Base" << endl;
}
};
class Derived : public Base
{
int b;
public:
Derived() {}
Derived(int a, int b) : Base(a), b(b){}
virtual void something()
{
cout << "Derived" << endl;
}
};
Simple tests
void setBase(Container &toSet)
{
Base base(15);
toSet.set(base);
}
void setDerived(Container &toSet)
{
Derived derived(10, 30);
toSet.set(derived);
}
int main()
{
Container co;
Base base(15);
Derived derived(10, 30);
Base *basePtr;
Derived *derivedPtr;
//This is fine
co.set(base);
basePtr = static_cast<Base *>(co.get());
basePtr->something();
//This is fine
co.set(derived);
derivedPtr = static_cast<Derived *>(co.get());
derivedPtr->something();
//Reset
basePtr = nullptr;
derivedPtr = nullptr;
//Dangling pointer!
setBase(co);
basePtr = static_cast<Base *>(co.get());
basePtr->something();
//Dangling pointer!
setDerived(co);
derivedPtr = static_cast<Derived *>(co.get());
derivedPtr->something();
return 0;
}
What you need to do is to define your memory ownership concretely.
Container::set accepts an instance of Abstract by reference, which usually does not imply an ownership transfer:
void set(Abstract &obj){...} // Caller retains ownership of obj, but now we have a weak reference to it
Then the onus of deletion is not on you.
Container::get returns a pointer which implies ownership, indicating that someone who calls set should not invalidate the passed object.
Abstract* get(){...}
This could be problematic, as you've stated.
You have a few options
Encode these memory ownership semantics within Container with proper documentation (Code by contract)
Use a smart pointer like std::shared_ptr
In the former case, whether it works or not depends on the user reading and understanding your API, and then behaving nicely with it. In the latter case, the pointer object owns itself, and will delete the allocated memory when the last instance goes out of scope.
void set(std::shared_ptr<Abstract> obj){...}
// now Container participates in the lifetime of obj,
// and it's harder to nullify the underlying object
// (you'd have to be intentionally misbehaving)
If you are worried about the object being deallocated elsewhere resulting in a dangling pointer, you could use boost smart pointers.
Boost smart pointers would provide you the service of book keeping and help to avoid such a case.
Some information can be found here :
smart pointers (boost) explained
This is what std::unique_ptr is for:
class Container
{
std::unique_ptr<Abstract> thing;
public:
void set(std::unique_ptr<Abstract> obj)
{
thing = obj;
}
Abstract* get()
{
return thing.get();
}
};
Now the Abstract object is "owned" by Container and will be cleaned up automatically when the Conatiner is destroyed.
If you want a pointer that might live longer, or might be shared between mulitple containers, use std::shared_ptr instead.
Class Base{
public:
...
void do_Something_base();
string identifier();
virtual void derived1_specific() {}; // nothing relevant to Base
virtual int derived2_specific(int) {};
};
Class Derived1:public Base {
public:
...
string identifier();
void derived1_specific();
};
Class Derived2:public Base {
public:
...
string identifier();
int derived2_specific();
};
int main() {
vector<Base*> owner;
/* push back some Derived1* & Derived2* to owner */
for (int i = 0; i < owner.size(); i++)
if (owner->identifier() == "d1")
owner->derived1_specific(int)
}
I have a larger program, that's the mechanics that make me confused. Should I write virtual function for every derived class? But this is very tedious.
I need to get and set some specific members, do some specific function in different child class. What is a smarter way or common way to do this?
thanks!
I would try really hard to find a common signature for the subclass-specific methods and then create one virtual function in the base class that can be called without some kind of ID-function.
Sometimes this can be achieved by passing some additional information needed for the subclass-specific function to the derived class's constructor, the common method could then be called e.g.
virtual void doClassSpecificStuff();
that uses member variables of your derived classes.
If you truly need differing return types etc, you might not want to inherit from a common ancestor OR not store all objects in the same container. Maybe composition works better than inheritance in your context (some class has-a specific worker object instead of is-a).
Edit: I erased the virtual solution since OP clarified that he needs to pass different parameters.
Since you have a way to know its actual type, there is nothing wrong in just casting to it, and then using it as that type:
Class Base{
public:
...
void do_Something_base();
string identifier();
};
Class Derived1:public Base {
public:
...
string identifier();
void TakeTwoInts(int x, int y);
};
Class Derived2:public Base {
public:
...
string identifier();
const char* ReturnAString();
};
int main() {
vector<Base*> owner;
/* push back some Derived1* & Derived2* to owner */
for (int i = 0; i < owner.size(); i++)
switch(owner[i]->identifier())
{
case "d1":
{
Derived1* d1 = static_cast<Derived1*>(owner[i]);
d1->TakeTwoInts(1,2);
break;
}
case "d2":
{
Derived2* d2 = static_cast<Derived2*>(owner[i]);
printf("%s",d2->ReturnAString());
break;
}
...
}
}
}
If you're not sure if the conversion is possible, use dynamic_cast instead: it returns a clean nullptr, rather than garbage, if the cast you ask is impossible.
By the way, note that the identifier() functions in the derived classes will never be called. Either you store the id in a variable accessible from Base, and then you don't need the function in each derived class, or you have to make identifier() a virtual function.
There are no :
virtual std::string Base::identifier()
In this case, when you have a Base* you cant call identifier() on it
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.
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();
Like in Game engines for example in XNA the update function is called automatically again and again. I want to know how i can achieve this in c++.
For ex:
class base
{
void Update();
};
class child1: public base
{
void Update();
}
class child2: public base
{
void Update();
}
void main()
{
base *obBase = new base();
obBase->Update(); /*This should call Update of Child1 and Child2 classes how can I do this*/
}
Just make it virtual:
class base
{
virtual void Update();
};
This will provide polymorphic behavior
And I assume you ment:
base *obBase = new child1(); //or new child2();
You can't access all instances of a derived classes of a base class.
What you need to do is to have some kind of a container, which will store all your objects of type Child1 and Child2 and then, when you decide, iterate through this container and call Update.
Something like:
SomeContainer< base* > myObjects;
// fill myObjects like:
// myObjects.insert( new ChildX(...) );
// ...
// iterate through myObjects and call Update
To be able to do this, you need to make Update a virtual function.
To prevent (potential) memory leaks, use smart pointers, instead of base*.
I guess you are trying to use polymorphism, something like this:
Base* obj1 = new Child1();
Base* obj2 = new Child2();
BaseManager* manager = new BaseManager(); //A class with a data struct that contains instances of Base, something like: list<Base*> m_objects;
manager->add(obj1); //Add obj1 to the list "m_objects"
manager->add(obj2); //Add obj2 to the list "m_objects"
manager->updateAll(); //Executes update of each instance in the list.