(Tip silme ile, bir sınıfla ilgili tür bilgilerinin bir kısmını veya tamamını, Boost.Any gibi gizlemek istedim .)
Bildiğim bunları paylaşırken , tip silme tekniklerinden de yararlanmak istiyorum. Umudum, birinin en karanlık saatinde düşündüğü çılgın bir teknik bulmak gibi. :)
Biliyorum, ilk ve en belirgin ve yaygın olarak ele alınan yaklaşım sanal işlevlerdir. Sınıfınızın uygulanmasını arayüz tabanlı bir sınıf hiyerarşisinde gizlemeniz yeterlidir. Birçok Boost kütüphanesi bunu yapar, örneğin Boost.Any bunu türünüzü gizlemek için yapar ve Boost.Shared_ptr bunu (de) ayırma mekanizmasını gizlemek için yapar.
Daha sonra, gerçek nesneyi Boostvoid*
gibi bir işaretçide tutarken, ayarlanmış işlevlere işlev işaretçileri olan bir seçenek vardır. İşlev, işlevin gerçek türünü gizlemek için yapar. Örnek uygulamalar sorunun sonunda bulunabilir.
Yani, asıl sorum için:
Başka hangi tip silme tekniklerini biliyorsunuz? Lütfen mümkünse örnek bir kod, kullanım örnekleri, onlarla olan deneyiminizi ve daha fazla okuma için bağlantılar sağlayın.
Düzenle
(Bunu bir cevap olarak eklemek isteyip istemediğimden emin olmadığımdan veya sadece soruyu düzenlediğimden, daha güvenli olanı yapacağım.) Sanal işlevler veya uğraşmadan
gerçek bir şeyi gizlemek için başka bir güzel teknik , bir Gman istihdam buraya alaka ile, sorumu tam olarak nasıl bu eserlerin üzerinde.void*
Ö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();
}
shared_ptr
bunu yansıtmaz, shared_ptr<int>
örneğin standart konteynerin aksine her zaman aynı olacaktır .
As
(s) işlevi bu şekilde uygulanamaz. Dediğim gibi, hiçbir şekilde kullanımı güvenli! :)
function
, shared_ptr
, any
Vb? Hepsi tatlı tatlı kullanıcı rahatlığı için tip silme kullanır.