Умные указатели и динамические _cast

Заранее извиняюсь, если на это уже отвечали, так как я искал и не нашел ответа.

ПРИМЕЧАНИЕ. :это ЯВЛЯЕТСЯ домашним заданием, поэтому, если вам неудобно отвечать, я полностью понимаю.

У меня есть следующий:

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

Теперь цель состояла в том, чтобы использовать динамическое _приведение для перехода туда и обратно, и хотя я нашел много интересных фактов об умных указателях ничего толком не объясняло , как это реализовано.

Я попытался просто получить адресное поле для pbase, а затем инициализировать pderived новым Ptr с этим адресом, но, конечно же, мои счетчики ссылок сбились.

Я попытался создать новый Ptr, содержащий ссылку на счетчик pderived, но тогда я не смог установить адресное поле pderived, поэтому тоже застрял.

Я сообщаю вам эту информацию, потому что :1. Я хочу отметить, что я работал над этим в течение достаточно долгого времени, прежде чем обратиться за помощью в Интернете и 2. Я хочу, чтобы вы знали, что я уже пробовал.

Здесь мне действительно не помешал бы совет.Только как получить:

pderived = <SOMETHINGSOMETHING>pbase<SOMETHINGSOMETHING>

Спасибо!

9
задан Bill the Lizard 15 December 2012 в 05:27
поделиться