I have implemented a basic object class in C++, and I want to make sure that I have implemented everything efficiently and safely, as I made a few mistakes while making it, which I corrected, but I could have left a few more mistakes behind:
class object
{
private:
class dummy
{
public:
dummy()
{
}
virtual ~dummy()
{
}
virtual const std::type_info &type() = 0;
virtual dummy *duplicate() const = 0;
virtual bool eq(object &) = 0;
};
template < typename _Ty > class data : public dummy
{
public:
data()
{
}
data(const _Ty &_Value)
: __data(_Value)
{
}
~data()
{
}
const std::type_info &type()
{
return typeid(_Ty);
}
data *duplicate() const
{
return new data<_Ty>(__data);
}
bool eq(object &_Obj)
{
return _Obj.cast<_Ty>() == __data;
}
_Ty __data;
};
dummy *d;
public:
object()
{
}
template < typename _Ty > object(const _Ty &_Value)
: d(new data<_Ty>(_Value))
{
}
object(const object &_Obj)
: d(_Obj.d->duplicate())
{
}
~object()
{
if (!empty())
{
delete d;
}
}
const std::type_info &type()
{
return (empty() ? typeid(void) : d->type());
}
object &operator=(object &_Rhs)
{
d = _Rhs.d->duplicate();
return *this;
}
object &swap(object &_Rhs)
{
std::swap(*this, _Rhs);
return *this;
}
template < typename _Ty > object &operator=(const _Ty &_Value)
{
d = new data<_Ty>(_Value);
return *this;
}
template < typename _Ty > _Ty cast()
{
if (type() == typeid(_Ty))
{
return static_cast<data<_Ty> *>(d)->__data;
}
throw std::exception("Invalid cast type");
}
bool operator==(object &_Rhs)
{
return (type() == _Rhs.d->type() ? d->eq(_Rhs) : false);
}
template < typename _Ty > bool operator==(_Ty _Value)
{
return (type() == typeid(_Ty) ? cast<_Ty>() == _Value : false);
}
bool operator!=(object &_Rhs)
{
return !(*this == _Rhs);
}
template < typename _Ty > bool operator!=(const _Ty &_Value)
{
return !(*this == _Value);
}
bool empty()
{
return !d;
}
};
{ }with= default;2) Get rid of names starting with underscore(s) \$\endgroup\$object(){}will default-initialize the data memberdummy *d;. Default-initialization for fundamental types means no initialization is performed. Subsequent calls ofempty()might returnfalse. Use value-initializationobject() : d() {}or explicit initializationobject() : d(nullptr) {}. Also, you don't need to checkif(!empty())beforedelete d;; deleting a nullptr value is safe. \$\endgroup\$std::swap(*this, _Rhs);won't do any magic. It will make a three copies (one copy-construction of a "temporary", and two copy-assignments). That's exactly what you want to avoid when supplying a customswapfunction. Also, you should consider making it a non-member friend function, see stackoverflow.com/a/5695855/420683 \$\endgroup\$