-6

C++ を使用してハンドル クラスを作成します。しかし、コードを実行すると、エラーが発生しました。

#pragma once

#include <iostream>
using std::cout;
using std::endl;

class BaseItem{
public:
    virtual BaseItem* clone()
    {
        return new BaseItem(*this);
    }
    virtual void sayHello()
    {
        cout<<"Hello, I am class BaseItem!"<<endl;
    }
};

class ChildItem:public BaseItem{
public:
    ChildItem* clone()
    {
        return new ChildItem(*this);
    }
    void sayHello(){
        cout<<"Hello, I am class ChildItem!"<<endl;
    }
};


template <typename T>
class Handle
{
public:
    Handle():baseItem(NULL), refCount(new size_t(0)) {}
    Handle(T& object):baseItem(object.clone()), refCount(new size_t(1)) {}

    Handle(const Handle<T>& other):baseItem(other.baseItem), refCount(new size_t(1)) {}

    Handle& operator= (const Handle<T>& other)
    {
        ++*other.refCount;
        dec_count();
        baseItem = other.baseItem;
        refCount = other.refCount;
        return *this;
    }

    const T* operator->() const {return baseItem;};
    const T& operator*() const {return *baseItem;};

    T* operator->() {return baseItem;};
    T& operator*() {return *baseItem;};

    virtual ~Handle(void)
    {
        dec_count();
    }
private:
    T *baseItem;
    std::size_t* refCount;
    void dec_count()
    {
        if (-- *refCount == 0 && baseItem != NULL)
        {
            delete baseItem;
            delete refCount;
        }
    }
};

これが主な機能です:

int _tmain(int argc, _TCHAR* argv[])
{
    BaseItem item1;
    ChildItem item2;

    vector<Handle<BaseItem> > vec;
    vec.push_back(Handle<BaseItem>(item1));
    vec.push_back(Handle<BaseItem>(item2));

    //for (vector<Handle<BaseItem> >::iterator iter = vec.begin();
    //  iter != vec.end(); iter++)
    //{
    //  
    //}
    return 0;
}

コードを実行すると、コードがクラッシュしました。コードをデバッグする方法がわかりません。これはエラーです: ここに画像の説明を入力

4

3 に答える 3

1

私が見ることができる問題は次のとおりです。

  • コピー コンストラクターは、新しい参照カウントを作成するのではなく、共有して参照カウントを増やす必要があります。
  • 基本クラスには仮想デストラクタが必要です。

最初の問題では、ハンドルをベクターにコピーした後に二重削除が発生します。両方のコピーは、それらがオブジェクトへの唯一の参照であると考えているため、両方ともそれを削除しようとします。これがおそらくクラッシュの原因です。

それらを修正すると、コードが正しく実行されているように見えます。それでも問題が解決しない場合は、失敗したテスト ケースをデバッガーでステップ実行することをお勧めします。

于 2013-09-12T09:59:39.847 に答える
0

参照カウントは、ハンドルの一部ではなく、実際のオブジェクトの一部である必要があります。ハンドルは、参照カウントをインクリメントおよびデクリメントするだけで、一度作成する必要があります。

template <typename T>
class RefCounted
{
    public:
        std::size_t refCount;
};

class BaseItem : public RefCounted<BaseItem> {

したがって、Handleで使用できるすべてのクラスはRefCounted から派生する必要があります。

template <typename T> class Handle
{
public:
    Handle():baseItem(NULL) {}
    Handle(T& object):baseItem(object.clone())) {++ other.refCount;}

    Handle(const Handle<T>& other):baseItem(other.baseItem) { ++ other.refCount; }

    Handle& operator= (const Handle<T>& other)
    {
        ++ other.refCount;
        baseItem = other.baseItem;
        return *this;
    }

    const T* operator->() const {return baseItem;};
    const T& operator*() const {return *baseItem;};

    T* operator->() {return baseItem;};
    T& operator*() {return *baseItem;};

    virtual ~Handle(void)
    {
        if (baseItem != NULL && -- (baseItem->refCount) == 0)
        {
            delete baseItem;
        }

    }
private:
    T *baseItem;

};

(免責事項: これは実用的なコードではなく、概念を説明しようとしただけです)

より良い実装を探している場合は、http://trac.webkit.org/browser/trunk/Source/WTF/wtf/RefCounted.hを参照してください。

于 2013-09-12T10:21:16.073 に答える