> Mechanism worked fine, then I googled and saw an comment on some website
> "inhertiance way for engine objects is old 20 years and it's very slow".
> My final questions are: is this good way to do it?
It may be more than twenty years old; but "very slow" may be more than fast enough for your particular requirement. As far as performance is concerned, one measurement is worth more than a thousand opinions.
Treat performance as a design constraint rather than as a design goal. I still remember this exchange with amusement:
> For a text file, the only portable way to do this is to read char by char, with escape sequence translations
> turned on, resizing the buffer as required, till end of file is reached. Doing this in C++ is painless.
>> 1. The above method is *incredibly* slow
>>
and is exactly why C programmers tend to hate C++ programmers.
More of this delightful stuff, if you want to peruse it:
http://www.cplusplus.com/forum/general/58900/
I was very new to this site at that time, this was my seventh or eight post; this closed account S6k9GNh0 (IIRC, the actual name was something like ComputerEquipped) was lording it over with some bazillions of posts. I was convinced that I had come to the wrong site, till I was reassured by the posts of Cubbi and m4ster r0shi.
As an aside, in my experience, C programmers who "hate C++ programmers", with a few notable exceptions, tend to be very poor C programmers.
> If inheritance way is good and if I should use std::vector for objects container.
> where should I store rectangle so it doesn't go out of scope?
> Should I use dynamic memory for it?
For a fast lookup based on name, a
map or
unordered_map with the key as the name of the object may be appropriate.
Using dynamic memory for the objects is not essential (for instance we could have array(s) of rectangle objects, array(s) of circle objects etc., with the map holding pointers to objects in these arrays). However, using dynamic memory may be more programmer efficient; then we wouldn't have to worry about synchronising the life-times of these arrays with the entries in he map. Perhaps use smart pointers to painlessly automate the management of life-time.
Something along these lines, perhaps:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
|
struct object
{
virtual ~object() noexcept = default ;
static std::size_t instance_count() noexcept { return objects.size() ; }
void destroy() noexcept { objects.erase( name_ ) ; }
static void destroy_all() noexcept { objects.clear() ; }
virtual const std::string& name() const noexcept { return name_ ; }
// other virtual functions eg.
virtual void draw() const = 0 ;
template < typename T, typename... OTHER_ARGS >
static bool make_object( const std::string& name, OTHER_ARGS&&... args )
{ return objects.emplace( name, std::make_unique<T>( name, std::forward<OTHER_ARGS>(args)... ) ).second ; }
static std::unique_ptr<object>& get( const std::string& name )
{
const auto iter = objects.find(name) ;
if( iter == objects.end() ) throw std::invalid_argument( "no object named \"" + name + '"' ) ;
else return iter->second ;
}
template < typename T > static T& get_as( const std::string& name )
{
const auto p = dynamic_cast<T*>( get(name).get() ) ;
if( p == nullptr ) throw std::invalid_argument( "incorrect type" ) ;
return *p ;
}
template< typename FN > static void for_each( FN&& fn )
{ for( auto& pair : objects ) std::forward<FN>(fn)( pair.second ) ; }
protected: object( std::string name ) noexcept : name_( std::move(name) ) {}
private:
const std::string name_ ;
// not copy assignable, not moveable
object( object&& ) noexcept = delete ;
object& operator= ( object&& ) noexcept = delete ;
// map name of object -> pointer to object
static std::unordered_map< std::string, std::unique_ptr<object> > objects ;
};
// in the implementation (.cpp) file
std::unordered_map< std::string, std::unique_ptr<object> > object::objects ;
|
http://coliru.stacked-crooked.com/a/fcae097b0076c23b
http://rextester.com/UWTJW88772