Помогите разобраться с заданием:
В первом уроке вы реализовали простой шаблон ValueHolder, в этом задании мы используем его чтобы написать класс Any (интересно, что не шаблонный), который позволяет хранить значения любого типа! Например, вы сможете создать массив объектов типа Any, и сохранять в них int-ы, double-ы или даже объекты Array. Подробности в шаблоне кода. Hint: в нешаблонном классе Any могут быть шаблонные методы, например, шаблонный конструктор.
// Эти классы реализовывать заново не нужно
struct ICloneable;
// Поле data_ типа T в классе ValueHolder
// открыто, к нему можно обращаться
template <typename T>
struct ValueHolder;
// Это класс, который вам нужно реализовать
class Any
{
// В классе Any должен быть конструктор,
// который можно вызвать без параметров,
// чтобы работал следующий код:
// Any empty; // empty ничего не хранит
// В классе Any должен быть шаблонный
// конструктор от одного параметра, чтобы
// можно было создавать объекты типа Any,
// например, следующим образом:
// Any i(10); // i хранит значение 10
// Не забудьте про деструктор. Все выделенные
// ресурсы нужно освободить.
// В классе Any также должен быть конструктор
// копирования (вам поможет метод clone
// интерфейса ICloneable)
// В классе должен быть оператор присваивания и/или
// шаблонный оператор присваивания, чтобы работал
// следующий код:
// Any copy(i); // copy хранит 10, как и i
// empty = copy; // empty хранит 10, как и copy
// empty = 0; // а теперь empty хранит 0
// Ну и наконец, мы хотим уметь получать хранимое
// значение, для этого определите в классе Any
// шаблонный метод cast, который возвращает
// указатель на хранимое значение, или нулевой
// указатель в случае несоответствия типов или
// если объект Any ничего не хранит:
// int *iptr = i.cast<int>(); // *iptr == 10
// char *cptr = i.cast<char>(); // cptr == 0,
// // потому что i хранит int, а не char
// Any empty2;
// int *p = empty2.cast<int>(); // p == 0
// При реализации используйте dynamic_cast,
// который мы уже обсуждали ранее.
};
Вот мое решение:
#include <iostream>
using namespace std;
struct ICloneable
{
virtual ICloneable* clone() const = 0;
virtual ~ICloneable() { }
};
template <typename T>
struct ValueHolder : ICloneable {
ValueHolder(const T& data): data_(data){}
T data_;
ValueHolder * clone() const {
return new ValueHolder(*this);
}
};
class Any
{
ICloneable * ptr;
public:
Any() : ptr(0) { }
template <class value_t>
Any(const value_t& v_) : ptr(new ValueHolder<value_t>(v_)) { }
Any(Any const & other) : ptr(other.ptr ? other.ptr->clone() : 0) {}
Any& operator=(Any const & other)
{
if(this->ptr)
delete this->ptr;
this->ptr = NULL;
if (other.ptr)
{
this->ptr=other.ptr->clone();
}
return *this;
}
template <class A>
Any& operator=(A const& other)
{
if(this->ptr)
delete this->ptr;
this->ptr = NULL;
if (other)
{
this->ptr=new ValueHolder<A>(other);
}
return *this;
}
~Any() { delete this->ptr; }
template <class T>
T* cast()
{
if (dynamic_cast<ValueHolder<T>*>(this->ptr))
{
return (T*)dynamic_cast<ValueHolder<T>*>(this->ptr);
}
else
{
return 0;
}
}
};
int main()
{
Any empty;
Any i(10);
cout << "[1] i=" << i.cast<int>() << endl;
Any copy(i);
cout << "[2] copy=" << copy.cast<int>() << endl;
empty = copy;
cout << "[3] empty=" << empty.cast<int>() << endl;
empty = 0;
cout << "[4] empty=" << empty.cast<int>() << endl;
int *iptr = i.cast<int>();
cout << "[5] *iptr=" << iptr << endl;
char *cptr = i.cast<char>();
cout << "[6] *cptr=" << cptr << endl;
Any empty2;
int *p = empty2.cast<int>();
cout << "[7] *p=" << p << endl;
Any a = 20;
cout << "[8] a=" << a.cast<int>() << endl;
a=0;
cout << "[9] a=" << a.cast<int>() << endl;
a='w';
cout << "[10] a=" << a.cast<char>() << endl;
return 0;
}
Засада в методе cast и [6] тесте. Как мне вернуть нулевой указатель при несоответствии типов char *cptr = i.cast<char>()?