SORU
27 Mart 2011, Pazar


Tür silme teknikleri

(Tür silme, tür bilgileri bir sınıf gibi biraz Boost.Any.) ile ilgili bazı ya da tüm saklanmışlar
Ayrıca biliyorum ki o, paylaşırken tür silme teknikleri ele almak istiyorum. Umudum biri kendi içinde en karanlık düşünce manyak tekniği bulmaktır. :)

İlk ve en belirgin ve yaygın olarak alınan yaklaşım, ben biliyorum ki, sanal fonksiyonlar. Sadece arayüzü sınıf bir hiyerarşi içinde sınıf uygulama gizlemek. Birçok kütüphane bunu, örneğin Boost Boost.Any Bu tür gizlemek için yapar Boost.Shared_ptr Bu (de)ayırma mekanik gizlemek için yapar.

Sonra Boost.Function eşleme gerçek tür gizlemek için yaptığı gibi void* bir işaretçi gerçek nesne tutarken şablon işlevleri için işlev işaretçileri ile bir seçeneği yoktur. Örnek uygulamalar soru sonunda bulunabilir.

Yani, benim gerçek soru için:
Diğer tür silme teknikleri hakkında ne biliyorsunuz? Lütfen mümkünse sağlamak, örnek bir kod ile, daha fazla okumak için doğduğunda onlarla deneyimini ve belki bağlantıları kullanabilirsiniz. Gerçekten harika ve tüm cevaplar için şimdiden teşekkürler!

Edit
Cevap olarak bu eklemek, ya da sadece soru düzenlemek için emin ol değildim (beri, sadece daha güvenli bir yaparım.)
Başka bir tekniğin çok güzel bir şey gerçek türü gizlemek içinolmadansanal fonksiyonlar veya void* işe yaramaz, GMan bu nasıl çalıştığı hakkında my question alaka here kullanır.


Örnek kod:

#include <iostream>
#include <string>

// NOTE: The class name indicates the underlying type erasure technique

// this behaves like the Boost.Any type w.r.t. implementation details
class Any_Virtual{
        struct holder_base{
                virtual ~holder_base(){}
                virtual holder_base* clone() const = 0;
        };

        template<class T>
        struct holder : holder_base{
                holder()
                        : held_()
                {}

                holder(T const& t)
                        : held_(t)
                {}

                virtual ~holder(){
                }

                virtual holder_base* clone() const {
                        return new holder<T>(*this);
                }

                T held_;
        };

public:
        Any_Virtual()
                : storage_(0)
        {}

        Any_Virtual(Any_Virtual const& other)
                : storage_(other.storage_->clone())
        {}

        template<class T>
        Any_Virtual(T const& t)
                : storage_(new holder<T>(t))
        {}

        ~Any_Virtual(){
                Clear();
        }

        Any_Virtual& operator=(Any_Virtual const& other){
                Clear();
                storage_ = other.storage_->clone();
                return *this;
        }

        template<class T>
        Any_Virtual& operator=(T const& t){
                Clear();
                storage_ = new holder<T>(t);
                return *this;
        }

        void Clear(){
                if(storage_)
                        delete storage_;
        }

        template<class T>
        T& As(){
                return static_cast<holder<T>*>(storage_)->held_;
        }

private:
        holder_base* storage_;
};

// the following demonstrates the use of void pointers 
// and function pointers to templated operate functions
// to safely hide the type

enum Operation{
        CopyTag,
        DeleteTag
};

template<class T>
void Operate(void*const& in, void*& out, Operation op){
        switch(op){
        case CopyTag:
                out = new T(*static_cast<T*>(in));
                return;
        case DeleteTag:
                delete static_cast<T*>(out);
        }
}

class Any_VoidPtr{
public:
        Any_VoidPtr()
                : object_(0)
                , operate_(0)
        {}

        Any_VoidPtr(Any_VoidPtr const& other)
                : object_(0)
                , operate_(other.operate_)
        {
                if(other.object_)
                        operate_(other.object_, object_, CopyTag);
        }

        template<class T>
        Any_VoidPtr(T const& t)
                : object_(new T(t))
                , operate_(&Operate<T>)
        {}

        ~Any_VoidPtr(){
                Clear();
        }

        Any_VoidPtr& operator=(Any_VoidPtr const& other){
                Clear();
                operate_ = other.operate_;
                operate_(other.object_, object_, CopyTag);
                return *this;
        }

        template<class T>
        Any_VoidPtr& operator=(T const& t){
                Clear();
                object_ = new T(t);
                operate_ = &Operate<T>;
                return *this;
        }

        void Clear(){
                if(object_)
                        operate_(0,object_,DeleteTag);
                object_ = 0;
        }

        template<class T>
        T& As(){
                return *static_cast<T*>(object_);
        }

private:
        typedef void (*OperateFunc)(void*const&,void*&,Operation);

        void* object_;
        OperateFunc operate_;
};

int main(){
        Any_Virtual a = 6;
        std::cout << a.As<int>() << std::endl;

        a = std::string("oh hi!");
        std::cout << a.As<std::string>() << std::endl;

        Any_Virtual av2 = a;

        Any_VoidPtr a2 = 42;
        std::cout << a2.As<int>() << std::endl;

        Any_VoidPtr a3 = a.As<std::string>();
        a2 = a3;
        a2.As<std::string>()  = " - again!";
        std::cout << "a2: " << a2.As<std::string>() << std::endl;
        std::cout << "a3: " << a3.As<std::string>() << std::endl;

        a3 = a;
        a3.As<Any_Virtual>().As<std::string>()  = " - and yet again!!";
        std::cout << "a: " << a.As<std::string>() << std::endl;
        std::cout << "a3->a: " << a3.As<Any_Virtual>().As<std::string>() << std::endl;

        std::cin.get();
}

CEVAP
18 Mayıs 2011, ÇARŞAMBA


C tipi silme teknikleri işlev işaretçileri (davranış için) void* (veri için) ile yapılır. "Farklı" yöntemler sadece şekilde farklı anlamsal şeker ekleyin. Sanal işlevler, örneğin, sadece anlamsal şeker

struct Class {
    struct vtable {
        void (*dtor)(Class*);
        void (*func)(Class*,double);
    } * vtbl
};

düşük: işlev işaretçileri.

O dedi, orada bir teknik, ben özellikle gibi, ama: shared_ptr<void>, çünkü patlar beyinleri kapalı insanlar kim bilmiyorum: kaydedebilir, herhangi bir veri shared_ptr<void> ve hala doğru yıkıcı aradı sonunda, çünkü shared_ptr yapıcı bir işlev şablonu ve kullanım türünün gerçek nesne geçti yaratma deleter tarafından varsayılan:

{
    const shared_ptr<void> sp( new A );
} // calls A::~A() here

Tabii ki, bu sadece her zamanki void*/-işaretçi fonksiyon türü silinme, ama çok uygun paketlenmiş.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Jana Williams

    Jana William

    17 AĞUSTOS 2011
  • kalabrandmusic

    kalabrandmus

    25 Kasım 2009
  • knopik96

    knopik96

    7 Mayıs 2011