Create a vector of sub classes?
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.
Member values not accessed in vector of instances of different subclasses
The problem is due to a misunderstanding on inheritance. If you redefine your Mesh
as follows, it would work as expected:
class Mesh : public Entity {
public:
//int index; // No don't redefine: here you'd have two different indexes
Mesh(int x) {this->index=x;};
void hit() override {} // extraa safety: use override instead of virtual to be sure to override
};
Online demo
Not related to the problem, but some more thoughts:
- You can of course only use the interface of the base class (here
Entity
). - It is not very prudent to expose the
index
member publicly. A safer option would be to have it private, and access it via a public getter. If the index should be set only at construction, the Entity constructor should take care of it, otherwise you could consider a public setter.
c++ Call subclass method in vector of base class type
How can I get access to the function com() which is only in object of subclass FiatMoney?
You would have to type-cast a Currency*
pointer into a FiatMoney*
pointer, but you can only do that when the pointer is actually pointing at a valid FiatMoney
object.
When you know the Currency*
pointer is pointing at a FiatMoney
object, you can use static_cast
at compile-time, eg:
static_cast<FiatMoney*>(Wallet[0])->com();
Otherwise, use dynamic_cast
at runtime to test the type of object being pointed at:
FiatMoney *fm = dynamic_cast<FiatMoney*>(Wallet[0]);
if (fm) fm->com();
Can I have method in class FiatMoney without previously declarate it as virtual function of Currency class?
Technically yes, though some people would argue that is not a good design choice when dealing with polymorphic classes.
Is this proper way of storing objects of different subclasses?
Technically yes, although Currency
should have a virtual destructor. You have to delete
the objects you new
, and a virtual destructor will allow you to call delete
on a Currency*
pointer to invoke derived class destructors without type-casting the pointer. And as such, you should consider storing smart pointers, like std::unique_ptr
, instead of raw pointers, so that delete
is called automatically for you.
Vector of subclasses
This is a serious bug:
virtual wsk clone()const{
r1 tmp=r1(*this);
return &tmp; // returning pointer to a local object
}
You are returning a pointer to a local object on stack. After clone()
returns, tmp
will be destroyed.
Dont use raw owning pointers. Use smart pointers instead, ex. unique_ptr
.
It's also a good habit to use override
in subclasses, so the compiler can emit an error if you override the wrong method. You don't need virtual
in subclasses, if subclasses are not meant to be derived from (it's an old way of marking virtual methods in a pre C++-11 era).
So the method becomes:
unique_ptr<robot> clone() const override
{
return make_unique<robot>(new r1(*this));
}
And for the list of robots you could use a vector of smart pointers vector<unique_ptr<robot>>
, so that all objects vector are automaticaly destroyed and memory freed.
C++11 vector holding 2 different subclasses, but not at the same time
boost::variant< std::vector<A>, std::vector<boost::variant<B,C>> >
describes your structure.
In C++17, replaced boost::
with std::
. The two are very similar, but not identical.
If you cannot use boost
, you'll have to basically write a variant
of your own.
Use is a bit awkward, but so are your type restrictions. Use gets easier in C++14 with auto-lambdas (which I believe boost variant visitor supports).
In C++14/17 you might do something like (pseudocode)
template<class F, class T, class=std::enable_if_t<!is_variant<T>{}>>
decltype(auto) visit( F&& f, T&& t ) {
return std::forward<F>(f)(std::forward<T>(t));
}
my_special_vec v;
visit( [&](auto&& v){
for (auto&& e:v) {
Base* b = visit( [&](auto&& e){
e.do_operation();
return std::addressof(e);
}, decltype(e)(e));
b->do_virtual_operation();
}
}, v );
which should non-virtually call e.do_operation()
on whichever of A
, B
or C
your vector contains, then call do_virtual_operation()
on the instance as a Base
.
And this is the easier, C++14 version. The C++11 version gets awkward with function objects and other mess.
Related Topics
Is It Safe to Memset Bool to 0
Can't Compile Easy Source in C++ and Opengl (Glfw) in Linux in Netbeans
Get Signatures of Exported Functions in a Dll
Accessing Static Member Through Invalid Pointer: Guaranteed to "Work"
How to Find the Current Directory
Implementing a Std::Vector Like Container Without Undefined Behavior
Load 32-Bit Shared Library from 64-Bit Application
Qt MACro Keywords Cause Name Collisions
How to Parse CSV Using Boost::Spirit
Timestamps for Embedded System
Convert Inline Assembly Code to C++
Implementation of Permutation, Combinations and Powerset in C++
What Is a Good Random Number Generator for a Game
Should Every Class Have a Virtual Destructor
C++:Handle Resources If Constructors May Throw Exceptions (Reference to Faq 17.4]