Say I have this class called Dog. Every dog has a different name but the same barking voice (which is loaded from a resource file).
class Dog {
public:
Dog(const string &name) : _name(name) {
_barkingVoice.load();
}
~Dog() {
_barkingVoice.free();
}
string getName() const { return _name; }
void bark() { _barkingVoice.play(); }
private:
string _name;
VoiceResource _barkingVoice;
};
I want to call _barkingVoice.load() only if the instance of Dog is the first one, and _barkingVoice.free() only if there are no more instances of Dog.
The obvious solution is to set _barkingVoice as static and keep a reference counter of Dog as a data member.
My question is if there's an easier way to do this. Maybe an std implementation or something like that.
Make a reusable class to encapsulate the reference counting:
template<class ResourceType, class OwnerType>
class RefCounted {
public:
RefCounted() { if (++_refCount == 1) _resource.load(); }
virtual ~RefCounted() { if (--_refCount == 0) _resource.free(); }
ResourceType& operator*() { return _resource; }
ResourceType* operator->() { return &_resource; }
private:
static unsigned _refCount;
static ResourceType _resource;
};
template<class T, class U> unsigned RefCounted<T, U>::_refCount = 0;
template<class T, class U> T RefCounted<T, U>::_resource;
class Dog {
public:
Dog(const string &name) : _name(name) { }
string getName() const { return _name; }
void bark() { _barkingVoice->play(); }
private:
string _name;
RefCounted<VoiceResource, Dog> _barkingVoice;
};
Every template instantiation will have their own _refCount and _resource.
The second template parameter is to handle cases where you instantiate RefCounted with the same ResourceType but want to have separate reference counting for those instantiations. E.g. if you add a Cat class and want it to have its own Refcounted<VoiceResource>:
class Cat {
// ...
private:
RefCounted<VoiceResource, Cat> _meowingVoice;
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With