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

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

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

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

26.09.2010, 03:22. Просмотров 4592. Ответов 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:

После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
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
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 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
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 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;
}
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. В общем вся объектная модель С++ ломается.
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
26.09.2010, 19:29  [ТС]     Абстрактный шаблонный класс #21
alexzak, Понято. Буду завтра днем думать как быть. Спасибо за информацию.

Добавлено через 9 часов 14 минут
3начит в этой 3адаче не стоит исполь3овать указатели? Чере3 объекты конкр. класса лучше? Да и вообще есть ли смысл разделять, если есть перегру3ка операторов ввода/вывода и резон есть-ли делать все же через абстрактный класс?

Не по теме:

Если не понятно что пишу извините. Спросони.



Добавлено через 2 часа 7 минут
Это возможно как-то сделать без переписывания всего? А то что-то совсем не хочется переписывать всю программу с нуля практически

Добавлено через 2 часа 20 минут
П.С. насколько я понимаю самый простой метод это пользоваться функциями, а не перегрузкой операторов, в таком случае проблем не будет... Но все же это как-то нехорошо...
alexzak
84 / 57 / 1
Регистрация: 07.08.2010
Сообщений: 185
26.09.2010, 21:23     Абстрактный шаблонный класс #22
Цитата Сообщение от Lavroff Посмотреть сообщение
3начит в этой 3адаче не стоит исполь3овать указатели? Чере3 объекты конкр. класса лучше? Да и вообще есть ли смысл разделять, если есть перегру3ка операторов ввода/вывода и резон есть-ли делать все же через абстрактный класс?
Правильно. Вообще, идея о том, что в Matr можно добавить функциональность ввода/вывода, унаследовав от него ConsoleMatr, плохая. Наследование для добавления функциональности - это пример неправильного его использования. В данном случае Matr не был изначально сделан как полиморфный класс. Поэтому когда пытаешься от него унаследоваться, возникают проблемы. Лучше добавить ввод/вывод через свободные операторы << и >>. В последнее время такой метод (свободные операторы и функции) стал очень популярен в С++, потому что он избавлен от проблем, возникающих при наследовании.
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
26.09.2010, 21:56  [ТС]     Абстрактный шаблонный класс #23
alexzak, Свободные операторы то есть? Пример можно? Операторы не в классе?
alexzak
84 / 57 / 1
Регистрация: 07.08.2010
Сообщений: 185
26.09.2010, 21:59     Абстрактный шаблонный класс #24
Да, те, для которых не надо изменять класс, например:
C++
1
2
ostream & operator<<(ostream & out, Matr const & m);
Matr operator+(Matr const & lhs, Matr const & rhs);
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
27.09.2010, 07:41  [ТС]     Абстрактный шаблонный класс #25
alexzak, Понято. Я тут пытаюсь что-то сделать. Почти доделал. Если получится - скину код.

Добавлено через 23 минуты
Кхм. Не помогают танцы с бубном. Не понимаю почему.

Код
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#ifndef _MATRIX_H_
#define _MATRIX_H_
 
namespace MatrSpace
{
    template<class T>
    class AbstractMatr
    {
    public:
        AbstractMatr() {}
        AbstractMatr(size_t n, size_t m);
        AbstractMatr(const AbstractMatr&);
        virtual ~AbstractMatr() {}
        void SetSize(size_t n, size_t m);
        inline const size_t GetRow() const {return Matrix.size();}
        inline const size_t GetCol() const {return Matrix[0].size();}
        virtual void input(std::ostream&)=0;
        virtual void output(std::istream&)=0;
    protected:
        std::vector<std::vector<T> > Matrix;
    };
 
    template<class T>
    class MathMatr:public AbstractMatr<T>
    {
    public:
        MathMatr():AbstractMatr() {}
        MathMatr(size_t n, size_t m):AbstractMatr<T>(n, m) {}
        MathMatr(const AbstractMatr<T>& Ob):AbstractMatr<T>(Ob) {}
        virtual ~MathMatr() {}
        MathMatr<T>& operator =(const MathMatr&);
        MathMatr<T> operator +=(const MathMatr&);
        MathMatr<T> operator +(const MathMatr&);
        MathMatr<T> operator *=(const MathMatr&);
        MathMatr<T> operator *(const MathMatr&);
        virtual void input(std::istream&) {}
        virtual void output(std::ostream&) {}
        template<class T2>
        friend std::ostream& operator <<(std::ostream&, const MathMatr<T2>& Ob);
        template<class T2>
        friend std::istream& operator >>(std::istream&, MathMatr<T2>& Ob);
        void random_fill();
    };
 
    template<class T>
    class ConsoleMatr:public MathMatr<T>
    {
    public:
        ConsoleMatr():MathMatr() {}
        ConsoleMatr(size_t n, size_t m):MathMatr(n, m) {}
        ConsoleMatr(const AbstractMatr<T>& Ob):MathMatr(Ob) {}
        virtual ~ConsoleMatr() {}
        void input(std::istream&);
        void output(std::ostream&);
    };
 
    template<class T>
    AbstractMatr<T>::AbstractMatr(size_t n, size_t m)
    {
        Matrix.resize(n);
        for(int i=0; i!=GetRow(); ++i)
        {
            Matrix[i].resize(m);
        }
    }
 
    template<class T>
    AbstractMatr<T>::AbstractMatr(const AbstractMatr<T> &Ob)
    {
        SetSize(Ob.GetRow, Ob.GetCol());
        for(int i=0; i!=Ob.GetRow(); ++i)
        {
            std::copy(Ob.Matrix[i].begin(), Ob.Matrix[i].end(), Matrix.begin());
        }
    }
 
    template<class T>
    void AbstractMatr<T>::SetSize(size_t n, size_t m)
    {
        if(GetRow!=0&&GetCol()!=0)
            Matrix.clear();
        Matrix.resize(n);
        for(int i=0; i!=GetRow(); ++i)
        {
            Matrix[i].resize(m);
        }
    }
 
    template<class T>
    MathMatr<T>& MathMatr<T>::operator =(const MathMatr<T>& Ob)
    {
        if(this==&Ob)
            return *this;
        SetSize(Ob.GetRow(), Ob.GetCol());
        for(int i=0; i!=GetRow(); ++i)
        {
            std::copy(Ob.Matrix[i].begin(), Ob.Matrix[i].end(), Matrix[i].begin());
        }
        return *this;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator +=(const MathMatr<T>& Ob)
    {
        if(GetRow()!=Ob.GetRow()&&GetCol()!=Ob.GetCol())
           throw std::string("Size of two matrix for sum must be equal!");
        for(int i=0; i!=Ob.GetRow(); ++i)
        {
           for(int j=0; j!=Ob.GetCol(); ++j)
           {
              Matrix[i][j]+=Ob.Matrix[i][j];
           }
        }
        return *this;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator +(const MathMatr<T>& Ob)
    {
        MathMatr<T> Temp(*this);
        Temp+=Ob;
        return Temp;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator *=(const MathMatr<T>& Ob)
    {
        if(GetCol()!=Ob.GetRow())
            throw std::string("Num of 1-st matrix cols must be equal to num of 2-nd matrix rows");
        MathMatr Temp(GetRow(), Ob.GetCol());
        for(int i=0; i!=Temp.GetRow(); ++i)
        {
           for(int j=0; j!=Temp.GetCol(); ++j)
           {
              Temp.Matrix[i][j]=0;
              for(int k=0; k!=GetCol(); ++k)
              {
                 Temp.Matrix[i][j]+=Matrix[i][k]*Ob.Matrix[k][j];
              }
            }
        }
        *this=Temp;
        return *this;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator *(const MathMatr<T>& Ob)
    {
        MathMatr<T> Temp(*this);
        Temp+=Ob;
        return Temp;
    }
 
    template<class T>
    void MathMatr<T>::random_fill()
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
             Matrix[i][j]=1+rand()%50;
          }
       }
    }
 
    template<class T>
    std::ostream& operator <<(std::ostream& os, const MathMatr<T>& Ob)
    {
       Ob.output(os);
       return os;
    }
 
    template<class T>
    std::istream& operator >>(std::istream& is, MathMatr<T>& Ob)
    {
       Ob.input(is);
       return is;
    }
 
    template<class T>
    void ConsoleMatr<T>::input(std::istream& is)
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
              std::cout<<"Enter Matrix ["<<i+1<<"]["<<j+1<<"]: ";
              is>>Matrix[i][j];
          }
       }
    }
 
    template<class T>
    void ConsoleMatr<T>::output(std::ostream& os)
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
              os<<std::setw(5)<<Matrix[i][j]<<' ';
          }
          std::cout<<std::endl;
       }
    }
}


Все бы ничего... Но при попытке вызова:
C++
1
   MathMatr<int> Ob1;
или
C++
1
   std::auto_ptr<AbstractMatr<int> > Ob(new ConsoleMatr<int>);
Пишется ошибка:
Error 1 error C2259: 'MatrSpace::ConsoleMatr<T>' : cannot instantiate abstract class c:\программирование\страуструп\глава 4\matirx\matirx\matrix.cpp 16

Всю голову уже переломал... Вроде бы все что нужно реализовано.

Добавлено через 34 минуты
Проблему нашел. Собственно, Проблема была в двух абстрактных функциях... Сделав класс конкретным стало лучше... Но ненамного...

Добавлено через 8 часов 39 минут
Все исправил... Однако только если первый класс не является абстрактным. В чем может быть проблема? Ведь насколько я понимаю наследование от абстрактного класса должно идти нормально...

Код:

...
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
#ifndef _MATRIX_H_
#define _MATRIX_H_
 
namespace MatrSpace
{
    template<class T>
    class AbstractMatr
    {
    public:
        AbstractMatr() {}
        AbstractMatr(size_t n, size_t m);
        AbstractMatr(const AbstractMatr&);
        virtual ~AbstractMatr() {}
        void SetSize(size_t n, size_t m);
        inline const size_t GetRow() const {return Matrix.size();}
        inline const size_t GetCol() const {return Matrix[0].size();}
        virtual void input(std::ostream&)=0;
        virtual void output(std::istream&)=0;
    protected:
        std::vector<std::vector<T> > Matrix;
    };
 
    template<class T>
    class MathMatr:public AbstractMatr<T>
    {
    public:
        //MathMatr(AbstractMatr<T>*P):Pointer(p) {}
        MathMatr():AbstractMatr() {}
        MathMatr(size_t n, size_t m):AbstractMatr<T>(n, m) {}
        MathMatr(const AbstractMatr<T>& Ob):AbstractMatr<T>(Ob) {}
        virtual ~MathMatr() {}
        MathMatr<T>& operator =(const MathMatr&);
        MathMatr<T> operator +=(const MathMatr&);
        MathMatr<T> operator +(const MathMatr&);
        MathMatr<T> operator *=(const MathMatr&);
        MathMatr<T> operator *(const MathMatr&);
        virtual void input(std::istream&) {}
        virtual void output(std::ostream&) {}
        template<class T2>
        friend std::ostream& operator <<(std::ostream&, MathMatr<T2>& Ob);
        template<class T2>
        friend std::istream& operator >>(std::istream&, MathMatr<T2>& Ob);
        void random_fill();
    protected:
        //AbstractMatr<T>*Pointer;
    };
 
    template<class T>
    class ConsoleMatr:public MathMatr<T>
    {
    public:
        ConsoleMatr():MathMatr() {}
        ConsoleMatr(size_t n, size_t m):MathMatr(n, m) {}
        ConsoleMatr(const AbstractMatr<T>& Ob):MathMatr<T>(Ob) {}
        virtual ~ConsoleMatr() {}
        ConsoleMatr<T>& operator =(const ConsoleMatr&);
        ConsoleMatr<T> operator +=(const ConsoleMatr&);
        ConsoleMatr<T> operator +(const ConsoleMatr&);
        ConsoleMatr<T> operator *=(const ConsoleMatr&);
        ConsoleMatr<T> operator *(const ConsoleMatr&);
        virtual void input(std::istream&);
        virtual void output(std::ostream&);
    };
 
    template<class T>
    AbstractMatr<T>::AbstractMatr(size_t n, size_t m)
    {
        Matrix.resize(n);
        for(int i=0; i!=GetRow(); ++i)
        {
            Matrix[i].resize(m);
        }
    }
 
    template<class T>
    AbstractMatr<T>::AbstractMatr(const AbstractMatr<T> &Ob)
    {
        SetSize(Ob.GetRow(), Ob.GetCol());
        for(int i=0; i!=Ob.GetRow(); ++i)
        {
            std::copy(Ob.Matrix[i].begin(), Ob.Matrix[i].end(), Matrix[i].begin());
        }
    }
 
    template<class T>
    void AbstractMatr<T>::SetSize(size_t n, size_t m)
    {
        if(GetRow()!=0&&GetCol()!=0)
            Matrix.clear();
        Matrix.resize(n);
        for(int i=0; i!=GetRow(); ++i)
        {
            Matrix[i].resize(m);
        }
    }
 
    template<class T>
    MathMatr<T>& MathMatr<T>::operator =(const MathMatr<T>& Ob)
    {
        if(this==&Ob)
            return *this;
        SetSize(Ob.GetRow(), Ob.GetCol());
        for(int i=0; i!=GetRow(); ++i)
        {
            std::copy(Ob.Matrix[i].begin(), Ob.Matrix[i].end(), Matrix[i].begin());
        }
        return *this;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator +=(const MathMatr<T>& Ob)
    {
        if(GetRow()!=Ob.GetRow()&&GetCol()!=Ob.GetCol())
           throw std::string("Size of two matrix for sum must be equal!");
        for(int i=0; i!=Ob.GetRow(); ++i)
        {
           for(int j=0; j!=Ob.GetCol(); ++j)
           {
              Matrix[i][j]+=Ob.Matrix[i][j];
           }
        }
        return *this;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator +(const MathMatr<T>& Ob)
    {
        MathMatr<T> Temp(*this);
        Temp+=Ob;
        return Temp;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator *=(const MathMatr<T>& Ob)
    {
    *   if(GetCol()!=Ob.GetRow())
            throw std::string("Num of 1-st matrix cols must be equal to num of 2-nd matrix rows");
        MathMatr Temp(GetRow(), Ob.GetCol());
        for(int i=0; i!=Temp.GetRow(); ++i)
        {
           for(int j=0; j!=Temp.GetCol(); ++j)
           {
              Temp.Matrix[i][j]=0;
              for(int k=0; k!=GetCol(); ++k)
              {
                 Temp.Matrix[i][j]+=Matrix[i][k]*Ob.Matrix[k][j];
              }
            }
        }
        *this=Temp;
        return *this;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator *(const MathMatr<T>& Ob)
    {
        MathMatr<T> Temp(*this);
        Temp*=Ob;
        return Temp;
    }
 
    template<class T>
    void MathMatr<T>::random_fill()
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
             Matrix[i][j]=1+rand()%50;
          }
       }
    }
 
    template<class T>
    std::ostream& operator <<(std::ostream& os, MathMatr<T>& Ob)
    {
       Ob.output(os);
       return os;
    }
 
    template<class T>
    std::istream& operator >>(std::istream& is, MathMatr<T>& Ob)
    {
       Ob.input(is);
       return is;
    }
 
    template<class T>
    void ConsoleMatr<T>::input(std::istream& is)
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
              std::cout<<"Enter Matrix ["<<i+1<<"]["<<j+1<<"]: ";
              is>>Matrix[i][j];
          }
       }
    }
 
    template<class T>
    void ConsoleMatr<T>::output(std::ostream& os)
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
              os<<std::setw(5)<<Matrix[i][j]<<' ';
          }
          std::cout<<std::endl;
       }
    }
 
    template<class T>
    ConsoleMatr<T>& ConsoleMatr<T>::operator =(const ConsoleMatr<T>& Ob)
    {
        if(this==&Ob)
            return *this;
        SetSize(Ob.GetRow(), Ob.GetCol());
        for(int i=0; i!=GetRow(); ++i)
        {
            std::copy(Ob.Matrix[i].begin(), Ob.Matrix[i].end(), Matrix[i].begin());
        }
        return *this;
    }
 
    template<class T>
    ConsoleMatr<T> ConsoleMatr<T>::operator +=(const ConsoleMatr<T>& Ob)
    {
        if(GetRow()!=Ob.GetRow()&&GetCol()!=Ob.GetCol())
           throw std::string("Size of two matrix for sum must be equal!");
        for(int i=0; i!=Ob.GetRow(); ++i)
        {
           for(int j=0; j!=Ob.GetCol(); ++j)
           {
              Matrix[i][j]+=Ob.Matrix[i][j];
           }
        }
        return *this;
    }
 
    template<class T>
    ConsoleMatr<T> ConsoleMatr<T>::operator +(const ConsoleMatr<T>& Ob)
    {
        ConsoleMatr<T> Temp(*this);
        Temp+=Ob;
        return Temp;
    }
 
    template<class T>
    ConsoleMatr<T> ConsoleMatr<T>::operator *=(const ConsoleMatr<T>& Ob)
    {
        if(GetCol()!=Ob.GetRow())
            throw std::string("Num of 1-st matrix cols must be equal to num of 2-nd matrix rows");
        ConsoleMatr Temp(GetRow(), Ob.GetCol());
        for(int i=0; i!=Temp.GetRow(); ++i)
        {
           for(int j=0; j!=Temp.GetCol(); ++j)
           {
              Temp.Matrix[i][j]=0;
              for(int k=0; k!=GetCol(); ++k)
              {
                 Temp.Matrix[i][j]+=Matrix[i][k]*Ob.Matrix[k][j];
              }
            }
        }
        *this=Temp;
        return *this;
    }
 
    template<class T>
    ConsoleMatr<T> ConsoleMatr<T>::operator *(const ConsoleMatr<T>& Ob)
    {
        ConsoleMatr<T> Temp(*this);
        Temp*=Ob;
        return Temp;
    }
}
#endif
Mr.X
Эксперт С++
3048 / 1693 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
27.09.2010, 12:55     Абстрактный шаблонный класс #26
А так не проще будет:
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
///////////////////////////////////////////////////////////////////////////////////////
#include <iostream>
///////////////////////////////////////////////////////////////////////////////////////
template<class T>
class T_matr
{
    T t_;//Для примера.
public:
    T_matr() : t_()
    {}
    //---------------------------------------------------------------------------------
    T get()
    {
        return t_;
    }
    //---------------------------------------------------------------------------------
    void set(T t)
    {
        t_ = t;
    }
};
///////////////////////////////////////////////////////////////////////////////////////
template<class T>
class T_matr_io
{
protected:
    T_matr<T>  matr;
 
public:
    virtual ~T_matr_io(){}
    virtual void  input()   = 0;
    virtual void  output()  = 0;
    //---------------------------------------------------------------------------------
    void  print_typename()
    {
        std::cout << typeid(T).name();
    }
};
///////////////////////////////////////////////////////////////////////////////////////
template<class T>
class T_matr_io_console : public T_matr_io<T>
{
public:
    void  input()
    {
        std::cout << "Ввод матрицы с элементами типа ";
        print_typename();
        std::cout << " с консоли ->   ";
        T t;
        std::cin >> t;
        matr.set(t);
    }
    //---------------------------------------------------------------------------------
    void  output()
    {
        std::cout << "Вывод матрицы с элементами типа ";
        print_typename();
        std::cout << " на консоль -> "                  
                  << matr.get()
                  << "."
                  << std::endl;    
    }
};
///////////////////////////////////////////////////////////////////////////////////////
template<class T>
class T_matr_io_cosmos : public T_matr_io<T>
{
public:
    void  input()
    {
        std::cout << "Ввод матрицы с элементами типа ";
        print_typename();
        std::cout << " из космоса."
                  << std::endl;    
    }
    //---------------------------------------------------------------------------------
    void  output()
    {        
        std::cout << "Вывод матрицы с элементами типа ";
        print_typename();
        std::cout << " в космос."
                  << std::endl;    
    }
};
///////////////////////////////////////////////////////////////////////////////////////
int main()
{
    std::locale::global(std::locale(""));
 
    T_matr_io<int>*  p_matr_io_console_int  = new T_matr_io_console<int>;
    T_matr_io<int>*  p_matr_io_cosmos_int   = new T_matr_io_cosmos<int>;
 
    p_matr_io_console_int->input();
    p_matr_io_console_int->output();
 
    p_matr_io_cosmos_int->input();
    p_matr_io_cosmos_int->output();
   
 
    T_matr_io<char>*  p_matr_io_console_char  = new T_matr_io_console<char>;
    T_matr_io<char>*  p_matr_io_cosmos_char   = new T_matr_io_cosmos<char>;
 
    p_matr_io_console_char->input();
    p_matr_io_console_char->output();
 
    p_matr_io_cosmos_char->input();
    p_matr_io_cosmos_char->output();
}
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
28.09.2010, 04:19  [ТС]     Абстрактный шаблонный класс #27
Mr.X, Красиво. Но придется опять перетрахивать класс...

Добавлено через 5 часов 51 минуту
Дико запутался... Вообще не знаю что делать... Пытался сделать с элементом класса - запутался в собственном коде... Что посоветуете?

Добавлено через 26 минут
Чудо. Оно заработало. А проблема была всего-лишь в одном маленьком недочете. Работает оно примерно вот так. Нормальный код?
И вопрос. Стоит ли делать методы в ConsoleMatr виртуальными или же нет?
Matrix.h
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
#ifndef _MATRIX_H_
#define _MATRIX_H_
 
namespace MatrSpace
{
    template<class T>
    class AbstractMatr
    {
    public:
        AbstractMatr() {}
        AbstractMatr(size_t n, size_t m);
        AbstractMatr(const AbstractMatr&);
        virtual ~AbstractMatr() {}
        void SetSize(size_t n, size_t m);
        inline const size_t GetRow() const {return Matrix.size();}
        inline const size_t GetCol() const {return Matrix[0].size();}
    protected:
        std::vector<std::vector<T> > Matrix;
    };
 
    template<class T>
    class MathMatr:public AbstractMatr<T>
    {
    public:
        MathMatr():AbstractMatr() {}
        MathMatr(size_t n, size_t m):AbstractMatr<T>(n, m) {}
        MathMatr(const AbstractMatr<T>& Ob):AbstractMatr<T>(Ob) {}
        virtual ~MathMatr() {}
        MathMatr<T>& operator =(const MathMatr&);
        MathMatr<T> operator +=(const MathMatr&);
        MathMatr<T> operator +(const MathMatr&);
        MathMatr<T> operator *=(const MathMatr&);
        MathMatr<T> operator *(const MathMatr&);
        virtual void input(std::istream&) {}
        virtual void output(std::ostream&) {}
        template<class T2>
        friend std::ostream& operator <<(std::ostream&, MathMatr<T2>& Ob);
        template<class T2>
        friend std::istream& operator >>(std::istream&, MathMatr<T2>& Ob);
        void random_fill();
    };
 
    template<class T>
    class IOMatr:public MathMatr<T>
    {
    public:
        IOMatr():MathMatr<T>() {}
        IOMatr(size_t n, size_t m):MathMatr(n, m) {}
        IOMatr(const AbstractMatr<T>& Ob):MathMatr(Ob) {}
        virtual ~IOMatr() {}
        virtual void input(std::istream&)=0;
        virtual void output(std::ostream&)=0;
    };
 
    template<class T>
    class ConsoleMatr:public IOMatr<T>
    {
    public:
        ConsoleMatr():IOMatr<T>() {}
        ConsoleMatr(size_t n, size_t m):IOMatr(n, m) {}
        ConsoleMatr(const AbstractMatr<T>& Ob):IOMatr(Ob) {}
        virtual ~ConsoleMatr() {}
        ConsoleMatr<T>& operator =(const ConsoleMatr&);
        ConsoleMatr<T> operator +=(const ConsoleMatr&);
        ConsoleMatr<T> operator +(const ConsoleMatr&);
        ConsoleMatr<T> operator *=(const ConsoleMatr&);
        ConsoleMatr<T> operator *(const ConsoleMatr&);
        virtual void input(std::istream&);
        virtual void output(std::ostream&);
    };
 
    template<class T>
    AbstractMatr<T>::AbstractMatr(size_t n, size_t m)
    {
        Matrix.resize(n);
        for(int i=0; i!=GetRow(); ++i)
        {
            Matrix[i].resize(m);
        }
    }
 
    template<class T>
    AbstractMatr<T>::AbstractMatr(const AbstractMatr<T> &Ob)
    {
        SetSize(Ob.GetRow(), Ob.GetCol());
        for(int i=0; i!=Ob.GetRow(); ++i)
        {
            std::copy(Ob.Matrix[i].begin(), Ob.Matrix[i].end(), Matrix[i].begin());
        }
    }
 
    template<class T>
    void AbstractMatr<T>::SetSize(size_t n, size_t m)
    {
        if(GetRow()!=0&&GetCol()!=0)
            Matrix.clear();
        Matrix.resize(n);
        for(int i=0; i!=GetRow(); ++i)
        {
            Matrix[i].resize(m);
        }
    }
 
    template<class T>
    MathMatr<T>& MathMatr<T>::operator =(const MathMatr<T>& Ob)
    {
        if(this==&Ob)
            return *this;
        SetSize(Ob.GetRow(), Ob.GetCol());
        for(int i=0; i!=GetRow(); ++i)
        {
            std::copy(Ob.Matrix[i].begin(), Ob.Matrix[i].end(), Matrix[i].begin());
        }
        return *this;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator +=(const MathMatr<T>& Ob)
    {
        if(GetRow()!=Ob.GetRow()&&GetCol()!=Ob.GetCol())
           throw std::string("Size of two matrix for sum must be equal!");
        for(int i=0; i!=Ob.GetRow(); ++i)
        {
           for(int j=0; j!=Ob.GetCol(); ++j)
           {
              Matrix[i][j]+=Ob.Matrix[i][j];
           }
        }
        return *this;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator +(const MathMatr<T>& Ob)
    {
        MathMatr<T> Temp(*this);
        Temp+=Ob;
        return Temp;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator *=(const MathMatr<T>& Ob)
    {
    *   if(GetCol()!=Ob.GetRow())
            throw std::string("Num of 1-st matrix cols must be equal to num of 2-nd matrix rows");
        MathMatr Temp(GetRow(), Ob.GetCol());
        for(int i=0; i!=Temp.GetRow(); ++i)
        {
           for(int j=0; j!=Temp.GetCol(); ++j)
           {
              Temp.Matrix[i][j]=0;
              for(int k=0; k!=GetCol(); ++k)
              {
                 Temp.Matrix[i][j]+=Matrix[i][k]*Ob.Matrix[k][j];
              }
            }
        }
        *this=Temp;
        return *this;
    }
 
    template<class T>
    MathMatr<T> MathMatr<T>::operator *(const MathMatr<T>& Ob)
    {
        MathMatr<T> Temp(*this);
        Temp*=Ob;
        return Temp;
    }
 
    template<class T>
    void MathMatr<T>::random_fill()
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
             Matrix[i][j]=1+rand()%50;
          }
       }
    }
 
    template<class T>
    std::ostream& operator <<(std::ostream& os, MathMatr<T>& Ob)
    {
       Ob.output(os);
       return os;
    }
 
    template<class T>
    std::istream& operator >>(std::istream& is, MathMatr<T>& Ob)
    {
       Ob.input(is);
       return is;
    }
 
    template<class T>
    void ConsoleMatr<T>::input(std::istream& is)
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
              std::cout<<"Enter Matrix ["<<i+1<<"]["<<j+1<<"]: ";
              is>>Matrix[i][j];
          }
       }
    }
 
    template<class T>
    void ConsoleMatr<T>::output(std::ostream& os)
    {
       for(int i=0; i!=GetRow(); ++i)
       {
          for(int j=0; j!=GetCol(); ++j)
          {
              os<<std::setw(5)<<Matrix[i][j]<<' ';
          }
          std::cout<<std::endl;
       }
    }
 
    template<class T>
    ConsoleMatr<T>& ConsoleMatr<T>::operator =(const ConsoleMatr<T>& Ob)
    {
        if(this==&Ob)
            return *this;
        SetSize(Ob.GetRow(), Ob.GetCol());
        for(int i=0; i!=GetRow(); ++i)
        {
            std::copy(Ob.Matrix[i].begin(), Ob.Matrix[i].end(), Matrix[i].begin());
        }
        return *this;
    }
 
    template<class T>
    ConsoleMatr<T> ConsoleMatr<T>::operator +=(const ConsoleMatr<T>& Ob)
    {
        if(GetRow()!=Ob.GetRow()&&GetCol()!=Ob.GetCol())
           throw std::string("Size of two matrix for sum must be equal!");
        for(int i=0; i!=Ob.GetRow(); ++i)
        {
           for(int j=0; j!=Ob.GetCol(); ++j)
           {
              Matrix[i][j]+=Ob.Matrix[i][j];
           }
        }
        return *this;
    }
 
    template<class T>
    ConsoleMatr<T> ConsoleMatr<T>::operator +(const ConsoleMatr<T>& Ob)
    {
        ConsoleMatr<T> Temp(*this);
        Temp+=Ob;
        return Temp;
    }
 
    template<class T>
    ConsoleMatr<T> ConsoleMatr<T>::operator *=(const ConsoleMatr<T>& Ob)
    {
        if(GetCol()!=Ob.GetRow())
            throw std::string("Num of 1-st matrix cols must be equal to num of 2-nd matrix rows");
        ConsoleMatr Temp(GetRow(), Ob.GetCol());
        for(int i=0; i!=Temp.GetRow(); ++i)
        {
           for(int j=0; j!=Temp.GetCol(); ++j)
           {
              Temp.Matrix[i][j]=0;
              for(int k=0; k!=GetCol(); ++k)
              {
                 Temp.Matrix[i][j]+=Matrix[i][k]*Ob.Matrix[k][j];
              }
            }
        }
        *this=Temp;
        return *this;
    }
 
    template<class T>
    ConsoleMatr<T> ConsoleMatr<T>::operator *(const ConsoleMatr<T>& Ob)
    {
        ConsoleMatr<T> Temp(*this);
        Temp*=Ob;
        return Temp;
    }
}
#endif


Matrix.cpp
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
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#include <vector>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <string>
 
#include "Matrix.h"
 
int main()
{ 
   using namespace MatrSpace;
   srand(static_cast<unsigned>(time(NULL)));
   ConsoleMatr<int> Ob1;
   size_t row, col;
   std::cout<<"Enter num of rows and cols for 1-st matrix: ";
   std::cin>>row>>col;
   Ob1.SetSize(row, col);
 
   int choise=0;
   std::cout<<"Enter 1 for fill matrix from keyboard\n"
      <<"Enter 2 for random fill matrix\n";
   std::cin>>choise;
   if(choise==1)
      std::cin>>Ob1;
   else if(choise==2)
      Ob1.random_fill();
   else
   {
      std::cerr<<"There is no such option\n";
      return 0;
   }
   std::cout<<std::endl;
   
   ConsoleMatr<int> Ob2;
   std::cout<<"Enter num of rows and cols for 2-nd matrix: ";
   std::cin>>row>>col;
   Ob2.SetSize(row, col);
 
   choise=0;
   std::cout<<"Enter 1 for fill matrix from keyboard\n"
      <<"Enter 2 for random fill matrix\n";
   std::cin>>choise;
   if(choise==1)
      std::cin>>Ob2;
   else if(choise==2)
      Ob2.random_fill();
   else
   {
      std::cerr<<"There is no such option\n";
      return 0;
   }
   std::cout<<std::endl;
 
   ConsoleMatr<int> Ob3;
   std::cout<<"First matrix\n\n"<< Ob1 <<'\n';
   std::cout<<"Second matrix\n\n"<< Ob2 <<'\n';
   try
   {
       Ob3=Ob1*Ob2;
   }
   catch(std::string&str) 
   {
      std::cout<<str<<'\n';
      return 0;
   }
   std::cout<<"Multy of first matrix to second matrix\n\n";
   std::cout<<Ob3<<'\n';
   return 0;
}
alexzak
84 / 57 / 1
Регистрация: 07.08.2010
Сообщений: 185
28.09.2010, 07:02     Абстрактный шаблонный класс #28
Пара замечаний к реализации:
Цитата Сообщение от Lavroff Посмотреть сообщение
C++
1
2
3
4
ConsoleMatr<T> operator +=(const ConsoleMatr&);
ConsoleMatr<T> operator +(const ConsoleMatr&);
ConsoleMatr<T> operator *=(const ConsoleMatr&);
ConsoleMatr<T> operator *(const ConsoleMatr&);
operator += и operator *= должны возвращать ConsoleMatr<T>&, а operator+ и operator* могут и должны быть const. И вообще, везде где ты возвращаешь *this, тип возвращаемого значения с большой вероятностью будет ссылкой.
C++
1
2
3
4
5
        template<class T>
        MathMatr<T>& MathMatr<T>::operator =(const MathMatr<T>& Ob)
        {
                if(this==&Ob)
                        return *this;
Оператор присваивания, который делает проверку на само-присваивание, с большой вероятностью не является exception-safe. И действительно, если в вызове SetSize произойдет исключение, то объект окажется в несколько странном состоянии.

Гораздо более надежной и простой является следующая реализация operator=:
C++
1
2
3
4
5
6
MathMatr & operator=(const MathMatr & other)
{
    MathMatr cpy(other);  // may throw
    cpy.swap(*this);  // can't throw
    return *this;
}
Причем swap должен быть небросающим. В твоем случае такой swap реализуется элементарно:
C++
1
2
3
4
void swap(MathMatr & other)
{
    Matrix.swap(other.Matrix);
}
C++
1
throw std::string("Size of two matrix for sum must be equal!");
Вместо выбрасывания просто строки было бы гораздо лучше использовать один из стандартных классов исключений. Например, сюда больше подойдет invalid_argument из stdexcept.
Mr.X
Эксперт С++
3048 / 1693 / 265
Регистрация: 03.05.2010
Сообщений: 3,867
28.09.2010, 11:49     Абстрактный шаблонный класс #29
Может быть в файле Matrix.h в строке 82 вместо
C++
1
2
3
4
5
6
7
8
9
    template<class T>
    AbstractMatr<T>::AbstractMatr(const AbstractMatr<T> &Ob)
    {
            SetSize(Ob.GetRow(), Ob.GetCol());
            for(int i=0; i!=Ob.GetRow(); ++i)
            {
                    std::copy(Ob.Matrix[i].begin(), Ob.Matrix[i].end(), Matrix[i].begin());
            }
    }
просто написать
C++
1
2
3
4
5
    template<class T>
    AbstractMatr<T>::AbstractMatr(const AbstractMatr<T> &Ob)
    {
        Matrix = Ob.Matrix;
    }
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
28.09.2010, 12:34     Абстрактный шаблонный класс
Еще ссылки по теме:

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; ...


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

Или воспользуйтесь поиском по форуму:
ForEveR
В астрале
Эксперт С++
7970 / 4732 / 320
Регистрация: 24.06.2010
Сообщений: 10,541
Завершенные тесты: 3
28.09.2010, 12:34  [ТС]     Абстрактный шаблонный класс #30
alexzak, То есть. Оперы должны выглядить примерно так?

C++
1
2
3
4
ConsoleMatr<T>& operator +=(const ConsoleMatr&);
const ConsoleMatr<T> operator +(const ConsoleMatr&) const;
ConsoleMatr<T>& operator *=(const ConsoleMatr&);
const ConsoleMatr<T> operator *(const ConsoleMatr&) const;
C++
1
2
3
4
MathMatr & operator=(const MathMatr & other)
{
    MathMatr cpy(other);  // may throw - копирование я так понимаю?
}
C++
1
2
3
4
void swap(MathMatr & other)
{
    Matrix.swap(other.Matrix);
}
Что должен делать этот метод? Менять значения двух объектов?
Yandex
Объявления
28.09.2010, 12:34     Абстрактный шаблонный класс
Ответ Создать тему
Опции темы

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