对象的共享资源

时间:2015-11-07 09:38:48

标签: c++

说我有这个名为Dog的课程。每只狗都有不同的名字,但是同样的吠叫声(从资源文件中加载)。

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;
};

我想仅在Dog的实例是第一个时调用_barkingVoice.load(),并且仅在没有Dog的实例时才调用_barkingVoice.free()

显而易见的解决方案是将_barkingVoice设置为static并将Dog的引用计数器保留为数据成员。

我的问题是,是否有更简单的方法来做到这一点。也许是std实现或类似的东西。

3 个答案:

答案 0 :(得分:2)

首先,为什么VoiceResource不是静态的?如果它在Dog的所有实例之间共享,那么它应该是。{否则,您需要在每次构造函数调用时加载或复制resuorce。

拥有一个静态变量static int instanceCount;,设置为0。在每个临时,复制和移动(C ++ 11)构造函数中递增它,在析构函数中递减它。这将使你有机会做你想做的事。

这基本上就像shared_ptr<T>那样工作,可能是一种在这里使用它而不是编写自己的代码的方法,我只是想不出来。

class Dog {
public:
    Dog(const string &name) : _name(name) {
        loadResource();
    }
    Dog(const Dog& b) : name(b.name) {            
        loadResource();
    }
    // only C++11:
    Dog(Dog&& b) : name(std::move(b.name))  {
        loadResource();
    }

    ~Dog() {
        freeResource();
        _barkingVoice.free();
    }

    string getName() const { return _name; }
    void bark() { _barkingVoice.play(); }

private:
    string _name;
    static VoiceResource _barkingVoice;
    static int instanceCount;

    static void loadResource() {
        if (instanceCount == 0) {
            _barkingVoice.load();
        }
        ++instanceCount;
    }
    static void freeResource() {
        --instanceCount;
        if (instanceCount == 0) {
            _barkingVoice.free();
        }
    }
};
int Dog::instanceCount = 0;

答案 1 :(得分:2)

创建一个可重用的类来封装引用计数:

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;
};

每个模板实例化都有自己的_refCount_resource

第二个模板参数用于处理使用相同RefCounted实例化ResourceType但希望对这些实例具有单独引用计数的情况。例如。如果您添加Cat类并希望它拥有自己的Refcounted<VoiceResource>

class Cat {
    // ...
private:
    RefCounted<VoiceResource, Cat> _meowingVoice;
};

答案 2 :(得分:1)

_barkingVoice设为std::shared_ptr<VoiceResource>

shared_ptr完全符合您的需要:使用引用计数来跟踪最后一个对象的删除,以及何时释放资源。