Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Массив в класс


Автор: albertn 6.9.2006, 11:52
Я хочу написать класс для работы с многомерным массивом например double.
По-идее в каждом классе должен быть массив объектов того-же класса, и так до последнего объекта. При такой структуре нет проблем в переопределении оператора []. Но возникает загвоздка - что делать с последним объектом, ведь он должен по оператору [] возвращать не объект, а число типа double.
Значит мне придестся создавать другой класс, который содержит не другие объекты, а числа. Но для универсальности один класс должен быть унаследован у другого, или они должны будут унаследованны у другого класса. Но тем не менее что там, что там есть переопределенный оператор [], но возвращает он не одно и тоже.
Посоветуйте как быть в этом случае.

Автор: Mayk 6.9.2006, 13:16
Цитата(albertn @  6.9.2006,  15:52 Найти цитируемый пост)
Но для универсальности один класс должен быть унаследован у другого, или они должны будут унаследованны у другого класса. 

Цитата(albertn @  6.9.2006,  15:52 Найти цитируемый пост)
По-идее в каждом классе должен быть массив объектов того-же класса, и так до последнего объекта.

Не совсем понял почему так.

Цитата(albertn @  6.9.2006,  15:52 Найти цитируемый пост)
Посоветуйте как быть в этом случае. 

Во-первых, если интерес практический, а не теоретический, то есть готовый
http://www.boost.org/libs/multi_array/doc/user.html#sec_example


Во-вторых можно переопределить operator()()
и с ним обращение к массиву можно реализовать как arr(1,2,4)=5;

В-третьих можно сделать operator[](Index i), и вызывать как
arr[Index(1,2,4)]=4;

Автор: MAKCim 6.9.2006, 21:11
Код

#define multi_array(N,Element)    \
    array_generator<N,Element>::type

template<int N, class Element, template<class> class Storage=vector>
    struct array_generator;

template<int N, class Element, template<class> class Storage>
    struct array_generator
{
    typedef Storage<typename array_generator<N-1,Element,Storage>::type>
        type;
};

template<class Element, template<class> class Storage>
    struct array_generator<0,Element,Storage>
{
    typedef Element type;
};

int main()
{
    multi_array(2,double) A;      // матрица
    multi_array(3,int) B;     // 3-х мерный массив
    return 0;
    return 0;
}

Автор: albertn 7.9.2006, 09:53
Цитата(Mayk @  6.9.2006,  13:16 Найти цитируемый пост)
Не совсем понял почему так.

Немного опишу мою цель:
Мне нужен класс для работы с тензорами, причем операции могут выполняться нестандартно. Обязательно необходим полный контроль над происходящим (никаких непонятных функций). Желательно переопределить стандартные операторы (+ - *). Также желательно, чтобы у любого тензора можно было выдернуть "хвостовую часть" тензора без особых проблем (к примеру так B = A[3]). Так-же желательно, чтобы можно было обращаться к элементам тензора в естественной для языка форме. Тензор будет неопределенной размерности (возможно даже переменной).

По-этому мне показалась наиболее оптимальной списочная структура. Но опять же возвращаюсь к "нашим баранам". Если же использовать два класса, то в одном из них должны содержаться объекты того-же класса. А чтобы в эту же переменную запихнуть объект другого класса, то надо, чтоб кто-то кого-то наследовал. Если не так, то поправьте меня. А использование одного класса может вызвать затруднение. 

Я попробывал переопределить опрератор присваивания от типа double, и вроде все стало нормально работать. Но все-равно чувствую, что сделать можно было-бы лучше.

За boost::multi_array спасибо, но времени на то, чтоб разбираться как его правильно унаследовать, и работать с ним имхо потребуется больше, чем написать что-то свое. К тому-же мне не нужно ничего такого громосткого, а все остальное все-равно дописывать придется.

Автор: MAKCim 7.9.2006, 14:57
Цитата

А чтобы в эту же переменную запихнуть объект другого класса, то надо, чтоб кто-то кого-то наследовал

void* ?

Автор: albertn 7.9.2006, 15:00
Цитата(MAKCim @ 7.9.2006,  14:57)
void* ?

А дальше? Как потом определить какого он класса? Придется тогда помечать в другой переменной, а это изврат.

Автор: MAKCim 7.9.2006, 15:07
Цитата

А дальше? Как потом определить какого он класса? Придется тогда помечать в другой переменной, а это изврат. 

а при наследовании придется сначала выделить интерфейс

Добавлено @ 15:10 
чем мой вариант выше не нравиться - динамический массив произвольной размерности
его можно инкапсулировать в класс и переопределить нужные операторы

Автор: albertn 7.9.2006, 16:38
Цитата(MAKCim @  7.9.2006,  15:07 Найти цитируемый пост)
а при наследовании придется сначала выделить интерфейс

Я уже написал, что сделал с одним классом, что оказалось проще, чем оба этих варианта, но по-моему осталась какой-то некрасивой.

Цитата(MAKCim @  7.9.2006,  15:07 Найти цитируемый пост)
чем мой вариант выше не нравиться - динамический массив произвольной размерности
его можно инкапсулировать в класс и переопределить нужные операторы 

Честно говоря я не хотел связываться с векторами, т.к. прога возможно будет использоваться в досовских приложениях (хотя и врятли)

Автор: likehood 7.9.2006, 17:39
albertn, может покажешь свой вариант.

Автор: albertn 11.9.2006, 09:09
Вот мой код:
Код

#include <stdio.h>

class tenzor
{
public:
    double value;
    tenzor **values;
    int count;
    tenzor(int n, int *rang);
    tenzor(const tenzor &o);
    ~tenzor();
    tenzor operator = (double v)
    {
        count = 0;
        value = v;
        return *this;
    }
    tenzor &operator [] (int i)
    {    
        if (i>=count || i<0)
            throw "123456";
        return *values[i];
    }
    operator double()
    {
        if (count!=0)
            throw "234523";
        return value;
    }
};

tenzor::tenzor(int n, int *rang)
{
    if (n>0)
    {
        count = *rang;
        values = new tenzor*[count];
        for (int i=0;i<count;++i)
            values[i] = new tenzor(n-1,rang+1);
    }
    else
        count = 0;
}

tenzor::tenzor(const tenzor &o)
{
    if (o.count>0)
    {
        count = o.count;
        values = new tenzor*[count];
        for (int i=0;i<count;++i)
            values[i] = new tenzor(*o.values[i]);
    }
    else
    {
        value = o.value;
        count = 0;
    }
}

tenzor::~tenzor()
{
    for (int i=0;i<count;++i)
        delete values[i];
    if (count>0)
        delete values;
}

int main()
{
    int z[]={3};
    tenzor b(1,z);
    for (int i=0;i<3;++i)
    {
        b[i]=i*10.0;
    }
    printf("%lf\t%lf\t%lf",(double)b[0],(double)b[1],(double)b[2]);
    return 0;
}

Пока сыроват, но главное работает.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)