Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
Рейтинг: Рейтинг темы: голосов - 35, средняя оценка - 4.83
ForEveR
В астрале
Эксперт С++
7969 / 4731 / 320
Регистрация: 24.06.2010
Сообщений: 10,539
Завершенные тесты: 3
#1

Абстрактный шаблонный класс - C++

26.09.2010, 03:22. Просмотров 4540. Ответов 45
Метки нет (Все метки)

Вообщем какое дело. У меня есть класс матрица, который сделан с использованием шаблонов и STL. В нем перегружены операторы ввода/вывода в поток(то, что их не врубить в динамический полиморфизм я уже понял).

Первый класс:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
    //Класс матрицы
    template<class T>
    class Matr
    {
    public:
       Matr();
       Matr(size_t n, size_t m);
       Matr(const Matr&);
       virtual ~Matr();
       void SetSize(size_t n, size_t m);
       const size_t GetRow() const {return Matrix.size();}
       const size_t GetCol() const {return Matrix[0].size();}
       template<class T2>
       friend std::ostream& operator <<(std::ostream& os, const Matr<T2>& Ob);
       template<class T2>
       friend std::istream& operator >>(std::istream& is, Matr<T2>& Ob);
       Matr<T>& operator =(const Matr&);
       Matr<T> operator +=(const Matr&);
       Matr<T> operator +(const Matr&);
       Matr<T> operator *=(const Matr&);
       Matr<T> operator *(const Matr&);
       void random_fill();
    protected:
       std::vector<std::vector<T> > Matrix;
    };
Определение функций писать не буду, пока это не нужно. Вряд ли 200 строк чем-то помогут. Виртуальными эту перегрузку не сделать. И если я пишу второй код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
template<class T>
class ConsoleMatr:public Matr<T>
{
public:
   ConsoleMatr():Matr() {}
   ConsoleMatr(size_t n, size_t m):Matr(n, m) {}
   ConsoleMatr(const Matr& Ob):Matr(Ob) {}
   template<class T2>
   friend std::ostream& operator <<(std::ostream& os, const ConsoleMatr<T2>& Ob);
   template<class T2>
   friend std::istream& operator >>(std::istream& is, ConsoleMatr<T2>& Ob);
};
И комментирую эти методы в исходном классе, то как реализовать динамический полиморфизм?

Пробую так.
C++
1
2
3
4
5
6
7
8
typedef std::auto_ptr<Matr<int> > MatrSP;
 
int main()
{
   MatrSP Ob(new ConsoleMatr);
   std::cin>>Ob;
   //
}
Пишет ошибку. Впринципе это понятно. Тогда вопрос, как реализовать??

А так же есть вариант оставить оба варианта. Но будут вызываться операторы ввода/вывода из класса Matr.

И следующий вопрос. Добавляю в первый класс две чисто виртуальные функции. Класс принимает вид:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    //Класс матрицы
    template<class T>
    class Matr
    {
    public:
       Matr();
       Matr(size_t n, size_t m);
       Matr(const Matr&);
       virtual ~Matr();
       void SetSize(size_t n, size_t m);
       const size_t GetRow() const {return Matrix.size();}
       const size_t GetCol() const {return Matrix[0].size();}
       template<class T2>
       friend std::ostream& operator <<(std::ostream& os, const Matr<T2>& Ob);
       template<class T2>
       friend std::istream& operator >>(std::istream& is, Matr<T2>& Ob);
       Matr<T>& operator =(const Matr&);
       Matr<T> operator +=(const Matr&);
       Matr<T> operator +(const Matr&);
       Matr<T> operator *=(const Matr&);
       Matr<T> operator *(const Matr&);
       void random_fill();
           virtual void input()=0;
           virtual void output()=0;
    protected:
       std::vector<std::vector<T> > Matrix;
    };
А второй.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
template<class T>
class ConsoleMatr:public Matr<T>
{
public:
   ConsoleMatr():Matr() {}
   ConsoleMatr(size_t n, size_t m):Matr(n, m) {}
   ConsoleMatr(const Matr& Ob):Matr(Ob) {}
   template<class T2>
   friend std::ostream& operator <<(std::ostream& os, const ConsoleMatr<T2>& Ob);
   template<class T2>
   friend std::istream& operator >>(std::istream& is, ConsoleMatr<T2>& Ob);
   void input();
   void output();
};
Вот так впринципе вполне неплохо идет полиморфизм. Но есть одно НО...

Ошибка происходит в этой функции.

C++
1
2
3
4
5
6
7
    template<class T>
    Matr<T> Matr<T>::operator *(const Matr<T> &Ob)
    {
          Matr<T> Obj(*this);   
          Obj*=Ob;
          return Obj;
    }
Нельзя инстанцинировать абстрактный класс... Что тоже понятно... Но непонятно, как тогда это реализовать. Или же забить на это и оставить как есть?
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
26.09.2010, 03:22     Абстрактный шаблонный класс
Посмотрите здесь:

Шаблонный класс - C++
Я запутался с шаблонами. Не пойму никак как вызвать конструктор с введенным в функции check_int() значением и как дальше вызвать функции...

Шаблонный класс - C++
Ребят, прошу Вашей помощи.. Программу я написала.. Она работает. Но теперь мне нужно переделать ее , используя шаблонный класс. Я...

Шаблонный класс - C++
#include &lt;iostream&gt; using namespace std; template &lt;class T&gt; class Vector{ private: int size, capacity; T* data; public: ...

Шаблонный класс - C++
День добрый. Пишу матричный калькулятор на шаблонном классе. Хочу добиться того, чтобы можно было оперировать с матрицами всех численных...

Шаблонный класс - C++
Подскажите как указать реализацию методов для шаблонного класса template &lt;class T_machine&gt; class hospital_room { ...

шаблонный класс - C++
реализован согласно &quot;Создание конструкторов и деструктора&quot; на шаблон класса с параметром -Тип данных в файле, редактируется (байт / слово /...

Шаблонный класс - C++
Как его реализовать??? Смысл я понимаю, но вот как записать...не знаю:cry:

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
26.09.2010, 03:50     Абстрактный шаблонный класс #2
C++
1
MatrSP Ob(new ConsoleMatr<int>)
вродеж как

Добавлено через 3 минуты
Цитата Сообщение от Lavroff Посмотреть сообщение
Нельзя инстанцинировать абстрактный класс... Что тоже понятно... Но непонятно, как тогда это реализовать. Или же забить на это и оставить как есть?
никак или объявить виртуальным
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
26.09.2010, 03:53     Абстрактный шаблонный класс #3
у меня один вопрос: задача в том, чтоб реализовать операторы ввода-вывода для типа "Т" ?
alex_x_x
бжни
2447 / 1652 / 84
Регистрация: 14.05.2009
Сообщений: 7,162
26.09.2010, 03:56     Абстрактный шаблонный класс #4
auto_ptr - бяка
C++
1
2
3
4
5
6
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<Matr<int> > MatrSP;
 
int main(){
    MatrSP sp( new ConsoleMatr<int> );
}
ForEveR
В астрале
Эксперт С++
7969 / 4731 / 320
Регистрация: 24.06.2010
Сообщений: 10,539
Завершенные тесты: 3
26.09.2010, 03:56  [ТС]     Абстрактный шаблонный класс #5
alex_x_x, Да) Так и было написано. А тут забыл(
auto_ptr конечно бяка, но сказали, если использовать указатели использовать именно его. У нас ребята и от этого офигевают чуть более чем полностью. Препод буст нам решил пока не давать.
ЗЫ: объявить виртуальным в каком смысле? Сам класс? Или виртуальное наследование?

niXman, Задача, чтобы разделить класс. На реализацию и собственно консольный ввод/вывод, дабы сам класс Matr мог быть актуален на любой платформе. То есть не только в консольных, но и в других. Должно быть сделано с использованием STL и шаблонов.
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
26.09.2010, 04:00     Абстрактный шаблонный класс #6
т.е. ты хочешь сделать так, чтоб ввод-вывод можно было использовать не только из/в консоли, а к примеру, и из файла/сокета?
ForEveR
В астрале
Эксперт С++
7969 / 4731 / 320
Регистрация: 24.06.2010
Сообщений: 10,539
Завершенные тесты: 3
26.09.2010, 04:02  [ТС]     Абстрактный шаблонный класс #7
niXman, Скорее хочу сделать так, чтобы реализация этих методов не зависила от остального класса, если это пригодится. Каждый ввод в свой класс. Пока у меня стоит задача только консольного ввода-вывода. Препод нам на таком примере объясняет концепции ООП впринципе.
niXman
Эксперт C++
3134 / 1446 / 49
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
26.09.2010, 04:13     Абстрактный шаблонный класс #8
Цитата Сообщение от Lavroff Посмотреть сообщение
чтобы реализация этих методов не зависила от остального класса
что-то ты напутал...
класс - шаблонный.
перегруженные операторы - шаблонные. в добавок, еще и дружественные функции этого класса
ну намешал...

объясни, что требуется?

Добавлено через 1 минуту
наверное я не уловил гениальность твоей идеи
ForEveR
В астрале
Эксперт С++
7969 / 4731 / 320
Регистрация: 24.06.2010
Сообщений: 10,539
Завершенные тесты: 3
26.09.2010, 04:15  [ТС]     Абстрактный шаблонный класс #9
niXman, Не моей. Препод попросил так сделать.

Вообщем...

У нас есть класс. Допустим тот же Matr. Шаблонный. В нем есть ввод/вывод в поток (консольный). Попросили сделать так, чтобы от Matr был производный шаблонный класс, в котором и реализуются ввод/вывод на консоль. Это реально? Если нет, то по какой причине, если да, то каким образом. Или не пытаться реализовать эту идею вцелом?
alexzak
84 / 57 / 1
Регистрация: 07.08.2010
Сообщений: 185
26.09.2010, 04:17     Абстрактный шаблонный класс #10
Ты задал два разных вопроса.

Первый ты уже похоже разрешил. Только я бы сделал вот так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
template<class T2>
std::ostream& operator <<(std::ostream& os, const Matr<T2>& Ob)
{
    Ob.output(os);
    return os;
}
 
template<class T2>
std::istream& operator >>(std::istream& is, Matr<T2>& Ob)
{
    Ob.input(is);
    return is;
}
Соответственные виртуальные функции - input(istream &) и output(ostream &). Никаких френдов не надо. И определять operator<< и >> для ColsoleMatr тоже не надо.

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

Решается это через идиому handle/body. Идея такая:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class MatrBase  // абстракный
{
public:
    virtual ~MatrBase() = 0 {}
 
    virtual
    MatrBase * clone() const = 0;  // клонируем себя
 
    void mult_op(MatrBase const * other)
    {
        // умножить *this на *other используя интерфейс MatrBase
    }
};
 
class ConsoleMatr : public MatrBase  // конкретный
{
public:
    ConsoleMatr * clone() const
    {
        return new ConsoleMatr(*this);
    }
};
 
class Matr  // handle
{
public:
    Matr(MatrBase * body) : m_body(body) {}
    ~Matr() { delete m_body; }
 
    Matr operator*(Matr const & other) const
    {
        MatrBase * product = other.m_body->clone();
        product->mult_op(m_body);
        return Matr(product);
    }
private:
    MatrBase * m_body;
};
ForEveR
В астрале
Эксперт С++
7969 / 4731 / 320
Регистрация: 24.06.2010
Сообщений: 10,539
Завершенные тесты: 3
26.09.2010, 04:29  [ТС]     Абстрактный шаблонный класс #11
alexzak, Красиво.
Первый вариант очень понравился.

Второй - тоже гуд, однако несколько не улыбает с этим настолько морочиться, т.к. это учебная программа и мои одногруппники лучше чем у меня была сделана в этот раз не сделают. Им итак надо за неделю понять стл, шаблоны, виртуальные функции, наследование и само ООП вообщем. Другое дело, что это действительно интересно. Надо будет запомнить об этой идиоме.
Я так понимаю ее приблизительный смысл - использование включения(или композиции, не совсем могу понять что из этого тут используется). У нас есть абстрактный класс, есть производный от абстрактного (который и есть главная задача реализовать), а так же есть класс в который входят указатели на объекты абстрактного класса и действие производится в основном через этот класс. Верно?
alexzak
84 / 57 / 1
Регистрация: 07.08.2010
Сообщений: 185
26.09.2010, 04:46     Абстрактный шаблонный класс #12
handle - это тот класс, с которым мы оперируем по-значению, как с обычными неполиморфным классом. Только так мы можем реализовать невиртуальные операторы умножения и т.д. А body - это полиморфный объект, с которым мы оперируем через указатель на базовый класс.

Это не композиция. Это скорее разделение интерфейса и реализации. Интерфейс здесь - это невиртуальный operator*. А реализация - это метод mult_op. (В данном случае он невиртуальный из-за простоты задачи. А мог бы быть, будь задача посложнее.)
ForEveR
В астрале
Эксперт С++
7969 / 4731 / 320
Регистрация: 24.06.2010
Сообщений: 10,539
Завершенные тесты: 3
26.09.2010, 04:57  [ТС]     Абстрактный шаблонный класс #13
alexzak, Относительно понял. А возможно это сделать не прибегая к паттернам? Виртуальными функциями или же какими-нибудь танцами с бубном? Просто интересно
alexzak
84 / 57 / 1
Регистрация: 07.08.2010
Сообщений: 185
26.09.2010, 05:09     Абстрактный шаблонный класс #14
Цитата Сообщение от Lavroff Посмотреть сообщение
А возможно это сделать не прибегая к паттернам?
Проблема фундаментального характера. Если Matr абстрактный, то по значению его возвратить нельзя. Но если сделать его конкретным, то можно реализовать operator* как в классе Matr, так и в классе ConsoleMatr:
C++
1
2
3
4
5
6
7
8
9
Matr Matr::operator*(Matr const & rhs) const
{
    // умножаем *this на rhs, оба одного типа, Matr
}
 
ConsoleMatr ConsoleMatr::operator*(ConsoleMatr const & rhs) const
{
    // умножаем *this на rhs, оба одного типа, ConsoleMatr
}
ForEveR
В астрале
Эксперт С++
7969 / 4731 / 320
Регистрация: 24.06.2010
Сообщений: 10,539
Завершенные тесты: 3
26.09.2010, 05:17  [ТС]     Абстрактный шаблонный класс #15
alexzak, Если Matr будет конкретный - я не особо вижу смысла переопределять операторы в производном классе. Перегруженные операторы ведь наследуются, а в данном случае оператор умножения матриц не изменится в любом случае. Ибо это стабильная формула. В чем смысл перегрузки оператора * для ConsoleMatr?
alexzak
84 / 57 / 1
Регистрация: 07.08.2010
Сообщений: 185
26.09.2010, 05:21     Абстрактный шаблонный класс #16
Цитата Сообщение от Lavroff Посмотреть сообщение
В чем смысл перегрузки оператора * для ConsoleMatr?
Как тогда ты сделаешь такое:
C++
1
2
3
ConsoleMatr m1;
ConsoleMatr m2;
ConsoleMatr m3 = m1 * m2;
ForEveR
В астрале
Эксперт С++
7969 / 4731 / 320
Регистрация: 24.06.2010
Сообщений: 10,539
Завершенные тесты: 3
26.09.2010, 05:25  [ТС]     Абстрактный шаблонный класс #17
alexzak, А для чего? Если для этого - вижу смысл, но, я собираюсь пользоваться дин. полиморфизмом, через auto_ptr<Matr<int> >;
Следовательно объекты будут типа Matr, но выделена под них память будет под тип ConsoleMatr.
C++
1
std::auto_ptr<Matr<int> > Ob(new ConsoleMatr<int>);
alexzak
84 / 57 / 1
Регистрация: 07.08.2010
Сообщений: 185
26.09.2010, 05:29     Абстрактный шаблонный класс #18
Цитата Сообщение от Lavroff Посмотреть сообщение
C++
1
std::auto_ptr<Matr<int> > Ob(new ConsoleMatr<int>);
Как ты такие объекты собираешься умножать?
C++
1
2
3
std::auto_ptr<Matr<int> > Ob(new ConsoleMatr<int>);
std::auto_ptr<Matr<int> > Ob2(new ConsoleMatr<int>);
std::auto_ptr<Matr<int> > Ob3 = ???
ForEveR
В астрале
Эксперт С++
7969 / 4731 / 320
Регистрация: 24.06.2010
Сообщений: 10,539
Завершенные тесты: 3
26.09.2010, 05:40  [ТС]     Абстрактный шаблонный класс #19
alexzak,
C++
1
2
std::auto_ptr<Matr<int> > Ob3(new ConsoleMatr<int>);
*Ob3=*Ob1 * *Ob2;
Что-то вроде такого. Хотя голова ща уже не особо хорошо думает.

Добавлено через 8 минут
Как пример:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
template<class T>
class Int
{
public:
    Int(){a=5;}
    virtual void input(){}
    virtual void output(){}
    Int<T> operator+(const Int<T>& Ob)
    {
        Int Temp;
        Temp.a=a+Ob.a;
        return Temp;
    }
protected:
    T a;
};
 
template<class T>
class ConsoleInt:public Int<T>
{
public:
    ConsoleInt():Int() {}
    void input()
    {
        std::cin>>a;
    }
    void output()
    {
        std::cout<<a<<'\n';
    }
};
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <memory>
 
#include "xfd.h"
 
int main()
{
    std::auto_ptr<Int<int> > Ob(new ConsoleInt<int>);
    Ob->input();
    Ob->output();
    std::auto_ptr<Int<int> > Ob2(new ConsoleInt<int>);
    Ob2->input();
    Ob2->output();
    std::auto_ptr<Int<int> > Ob3(new ConsoleInt<int>);
    *Ob3=*Ob+*Ob2;
    Ob3->output();
    return 0;
}
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
26.09.2010, 05:44     Абстрактный шаблонный класс
Еще ссылки по теме:

vector (шаблонный класс) - C++
Нужно создать простенький шаблонный класс вектор Подскажите пожалуйста , как написать запись элемента в начало вектора и в конец...

Шаблонный класс vector - C++
Всем привет. Помогите создать шаблонный класс vector и массив который хранит значения template&lt;typename T, size_t size&gt; class array{ ...

Дружественный шаблонный класс - C++
Доброго времени суток. Есть пример из книги (создание списка). Вот код: #ifndef LISTND_H #define LISTND_H template &lt;class...

Указатель на шаблонный класс - C++
Есть ли возможность инициализировать указатель на класс с шаблоном, но не указав при этом тип, ну т.е. написать не так Value_Class...

Шаблонный класс Стек - C++
прошу помочь разобраться с кодом. вопросы выделил по ходу кода. #ifndef _STACKNODE_H_ #define _STACKNODE_H_ #include &lt;string&gt; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
alexzak
84 / 57 / 1
Регистрация: 07.08.2010
Сообщений: 185
26.09.2010, 05:44     Абстрактный шаблонный класс #20
В выражении '*Ob3 = *Ob1 * *Ob2' не только operator* должен возвратить результать по-значению, что возможно только если 1) оба класса Matr и ConsoleMatr - конкретные, 2) для каждого из них определён operator* возвращающий значение правильного типа. Но и operator= должен быть виртуальным (тип выражения *Ob3 - Matr&, а не ConsoleMatr&), что само по себе уже странно. А невиртуальный operator= сделает slicing, т.е. он присвоит в объекте Ob3 только часть из базового Matr, но не весь ConsoleMatr. В общем вся объектная модель С++ ломается.
Yandex
Объявления
26.09.2010, 05:44     Абстрактный шаблонный класс
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru