13

見たところ答えが見つからなかったので、すでに答えられていた場合は、あらかじめお詫び申し上げます。

注:これは宿題なので、答えるのが不快だと感じた場合は、完全に理解しています。

私は次のものを持っています:

ptr.h:

template<typename T>
class Ptr {
    T* address;
    size_t* counter;
    Ptr(T* address) : address(address), counter(new size_t(1)) { }
    Ptr(const Ptr& other) : address(other.address), counter(other.counter) 
    { 
        ++(*counter); 
    }
    virtual ~Ptr() { 
        if (0 == --(*counter)) { delete address; delete counter; } 
    }
    Ptr& operator=(const Ptr& right) {
        if (address != right.address) {
            if (0 == --(*counter)) { delete address; delete counter; }
            address = right.address;
            counter = right.counter;
            ++(*counter);
        }
        return *this;
    }
    T& operator*()  const { TRACE(address); return *address; }
    T* operator->() const { TRACE(address); return address;  }
    T* raw()        const { TRACE(addr); return addr;  }
};

main.cc:

#include <iostream>
#include "ptr.h"

using std::cout;
using std::endl;


class Base {
public:
    Base()  { std::cout << "Base()" << std::endl; }
    virtual ~Base() { std::cout << "~Base()" << std::endl; }
    virtual std::string str() { return "In Base::str()"; }
};

class Derived: public Base {
public:
    Derived()  { std::cout << "Derived()" << std::endl; }
    ~Derived() { std::cout << "~Derived()" << std::endl; }
    std::string str() { return "In Derived::str()"; }
};



int main() {
Ptr<Base> base(new Base());
Ptr<Derived> derived(new Derived());

Ptr<Base> pbase(0);
Ptr<Derived> pderived(0);

    // upcasting can be done like this, but is it the best way?
    pbase = *((Ptr<Base>*)(&derived));
    cout << pbase->str() << endl;   // outputs: "In Derived::str()"

    /* 
     * downcasting should be done using dynamic_casts
     * but how can I downcast here? 
     * what do I know so far:
     * 1. just because Derived is a subclass of Base does not mean Ptr<Derived> is a 
     * subclass of Ptr<Base> so there is no hierarchy between the two so I cannot 
     * really use dynamic_casts here
     * 2. The dynamic_cast I do use is sort of useless no? since pbase is a Ptr<Base>
     */
    pderived = *((Ptr<Derived>*)(dynamic_cast<Ptr<Base>*>(&pbase)));
    cout << pderived->str() << endl;


return 0;
}

さて、目標はdynamic_castを使用して前後に移動することでした。スマートポインターに関する興味深い情報をたくさん見つけましたが、これがどのように実装されているかを実際に説明するものは何もありませんでした。

pbaseのアドレスフィールドを取得し、そのアドレスを使用してpderiveを新しいPtrに初期化しようとしましたが、もちろん、参照カウントがすべて台無しになりました。

pdifferentのカウンターへの参照を保持する新しいPtrを作成しようとしましたが、pducedのアドレスフィールドを設定できなかったため、そこでも行き詰まりました。

私は皆さんにこの情報を伝えています。理由は次のとおりです。1。オンラインで助けを求める前に、かなり長い間これに取り組んできたことを強調したい。2.私がすでに試したことを知ってほしい。

私はここで本当にいくつかのアドバイスを使うことができました。入手方法:

pderived = <SOMETHINGSOMETHING>pbase<SOMETHINGSOMETHING>

ありがとう!

4

1 に答える 1

7

通常、スマートポインタークラスは、基になるスマートポインターオブジェクトを適切に処理する動的キャストラッパーを公開します。たとえば、C++0xにはdynamic_pointer_cast関数があります。特に多重継承がある場合は、必要なスーパークラスを取得するためにサブクラス内の右オフセットに*((Ptr<Derived>*)(dynamic_cast<Ptr<Base>*>(&pbase)));ある内部ポインターを調整しないため、壊れることがあり、壊れることに注意してください。address

実装レベルでは、refcountingスマートポインタクラスは通常、各スマートポインタに2つのポインタを持ちます。1つはオブジェクトを直接指し(ポインタがどのタイプでも適切にキャストされます)、もう1つは参照カウント、元のオブジェクトへのポインタ、および削除ルーチンへのポインタを含む構造体を指します。これにより、ポインタのキャストされたバリアントが元のオブジェクトを正しく取り戻し、そのデストラクタを呼び出すことができます。現在、あなたはまっすぐに指していますがsize_t、それはあなたにこの情報を与えません。

いずれにせよ、デストラクタに対してこの間接参照を取得すると、これらのスマートポインターをキャストするときに、外側のポインターのみをキャストできます。破壊時間がロールアラウンドするときのために、この内部参照カウント構造をそのままにしておきます。

もちろん、実際にこれをすべてコードに変換することは、読者の練習問題として残されています:)

于 2012-04-21T23:23:07.763 に答える