Создать производный класс ТРОИЧНЫЙ ВЕКТОР от класса Vector

Shepard90

Народ!!! Please help me! Задолбался уже! Вобщем такое задание:Создать производный класс ТРОИЧНЫЙ ВЕКТОР от класса Vector. Компоненты вектора принимают значения из множества {0,1,2}. Методы: a) конструктор без параметров; b) конструктор, принимающий в качестве параметров указатель на массив целого типа и размер вектора; c) конструктор копирования; d) деструктор; e) проверка двух векторов на ортогональность (два троичных вектора называются ортогональными, если в них существует пара одноименных компонент, имеющих в одном из векторов значение 0, а в другом – 1); f) метод возвращает число компонент в векторе, принимающих значение 2. Переопределить операции: a) присваивание (=); b) поразрядная конъюнкция (пересечение) двух не ортогональных векторов (&): 0&0=0, 1&1=1, 2&2=2, 0&2=0, 2&0=0, 1&2=1, 2&1=1; c) индексирование ([]). Вот то, что я сумел накатать:
#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include <iostream>
using namespace std;
 
class Vector
{
 protected:
  int *mass; // указатель на начало вектора
  int count; // количество элементов в векторе
 public:
  Vector();
  Vector(int i); // конструктор (назначен параметр по умолчанию)
  ~Vector(); // деструтор (не может иметь параметров)
 int item(int i); // возвращает указанный элемент
  void  assign(int i, int x); // назначение элемента
  int num(); // возвращает число элементов (inline)
  int norm(); // возвращает квадрат нормы вектора
};
 
Vector::Vector()
{
}
Vector::Vector(int i)
{ int j;
  count=i;
  int *mass=new int[count];
  for (j=0; j<count; j++) *(mass+j)=0;
  cout << "vector created " << count << "\n";
}
 
Vector::~Vector()
{ delete mass;
 cout << "vector destroyed\n";
}
 
int Vector::item(int i)
{  if ((i>=0) && (i<count)) return *(mass+i);
  else {cout << "Error in vector::item"; return 0;}
}
 
void Vector::assign(int i, int x)
{
  if ((i>=0) && (i<count))  *(mass+i)=x;
  else cout << "Error in vector::assign";
}
int Vector::num() 
      { return count; }
int Vector::norm()
{ int i;
  int x=0;
  for (i=0; i<count; i++) x+=mass[i]*mass[i];
  return x;
}
 
 
class threeVector: public Vector
{
public:
    threeVector();//конструктор без параметрров
    threeVector(int *arr, int n);//передаю указатель на массив и длину массива
    threeVector(int n);//только длину
    ~threeVector();//деструктор
    threeVector(const threeVector &);//конструктор-копировщик
    void OrtVectors(const threeVector &);//проверка на ортогональность
    int SearchKomp(int *mass,int count);// поиск компонента вектора
    
};
threeVector::threeVector():Vector()
{
    int j;
  count=0;
  int *mass=new int[count];
  for (j=0; j<count; j++) *(mass+j)=0;
  cout << "threeVector created " << count << "\n";
}
threeVector::threeVector(int *arr, int n):Vector(n)
{
    *mass=*arr;
     cout << "threeVector created " << count << "\n";
}
threeVector::threeVector(int n):Vector(n)
{
    cout<<"threeVector created "<<count<<"\n";
}
threeVector::~threeVector()
{
    delete mass;
    cout<<"threeVector destroed\n";
}
threeVector::threeVector(const threeVector &rhs) 
{
    int *mass=new int[count];
    *mass=rhs.item(0); //ТУТ ОШИБКА!!!
}
 
int _tmain(int argc, _TCHAR* argv[])
{
    return 0;
}
Я понимаю, что жесть. Но может какими-нибудь советами поможете, подскажете чуть-чуть. Просто уже сил нету. Сейчас нахожусь на стадии написания производного класса, а именно конструктора-копировщика. Компилятор выдает следующую ошибку: (95)error C2662: 'Vector::item' : cannot convert 'this' pointer from 'const threeVector' to 'Vector &'Я так понимаю, что, пытаясь использовать метод базового класса Item для написания копировщика, в качестве параметра беру ссылку на объект производного класса. Вследствие этого компилятор ругается. Можно ли решить эту проблему "по-быстрому", или надо писать аналог метода Item для производного класса.Ну кто-нибудь посоветуйте что-нибудь - с места сдвинуться не могу! через два дня сдаватьКароч, класс я вроде добил. Но уже при написании клиентской части вылезли новые косяки. Ошибка возникает в момент создания объектов. Почему-то после выполнения конструктора пропадает адрес массива, указатель на который является защищенной переменной базового класса. Че я опять не так сделал???
// Laba7.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include <iostream>
using namespace std;
 
class Vector
{
protected:
  int *mass; // указатель на начало вектора
  int count; // количество элементов в векторе
 public:
  Vector();
  Vector(int i); // конструктор (назначен параметр по умолчанию)
  ~Vector(); // деструтор (не может иметь параметров)
 int item(int i) const; // возвращает указанный элемент
  void  assign(int i, int x); // назначение элемента
  int num(); // возвращает число элементов (inline)
  int norm(); // возвращает квадрат нормы вектора
};
 
Vector::Vector()
{
}
Vector::Vector(int i)
{ int j;
  count=i;
  int *mass=new int[count];
  for (j=0; j<count; j++)
  {
      mass[j]=0;
  }
  cout << "vector created " << count << "\n";
}
 
Vector::~Vector()
{ delete mass;
 cout << "vector destroyed\n";
}
 
int Vector::item(int i) const
{  if ((i>=0) && (i<count)) return *(mass+i);
  else {cout << "Error in vector::item"; return 0;}
}
 
void Vector::assign(int i, int x)
{
  if ((i>=0) && (i<count))  *(mass+i)=x;
  else cout << "Error in vector::assign";
}
int Vector::num() 
      { return count; }
int Vector::norm()
{ int i;
  int x=0;
  for (i=0; i<count; i++) x+=mass[i]*mass[i];
  return x;
}
 
 
class threeVector: public Vector
{
public:
    threeVector();//конструктор без параметрров
    threeVector(int *arr, int n);//передаю указатель на массив и длину массива
    threeVector(int n);//только длину
    ~threeVector();//деструктор
    threeVector(threeVector &);//конструктор-копировщик
    void OrtVectors(threeVector Vec1, threeVector Vec2);//проверка на ортогональность
    int SearchKomp(threeVector Vec1);// поиск компонента вектора
    threeVector & operator=(threeVector &rhs);
    int & operator[](int i);
    threeVector operator*(threeVector &rhs);
    void SetKomp(int x,int i);
};
threeVector::threeVector():Vector()//конструктор
{
    int j;
  count=1;
  int *mass=new int[count];
  for (j=0; j<count; j++) *(mass+j)=0;
  cout << "threeVector created " << count << "\n";
}
threeVector::threeVector(int *arr, int n):Vector(n)//конструктор
{
    *mass=*arr;
     cout << "threeVector created " << count << "\n";
}
threeVector::threeVector(int n):Vector(n)//конструктор
{
    cout<<"threeVector created "<<count<<"\n";
}
threeVector::~threeVector()//деструктор
{
    delete mass;
    cout<<"threeVector destroed\n";
}
threeVector::threeVector(threeVector &rhs) //коструктор-копировщик
{
    int *mass=new int[count];
    *mass=rhs.item(0);
}
void threeVector::OrtVectors(threeVector Vec1, threeVector Vec2)
{
    int i;
    int len;
    if(Vec1.num()<Vec2.num())
    {len=Vec1.num(); }
    else 
    {len=Vec2.num();}
    for(i=0;i<len;i++)
    {
        if(Vec1.item(i)==0 && Vec2.item(i)==1 || Vec1.item(i)==1 && Vec1.item(i)==0) 
        {
            printf("Vectors ortogonal");
            break;
        }
        else
        {
            if(i==len-1) printf("Vetors not ortogonal");
        }
    }
        
}
 
int threeVector::SearchKomp(threeVector Vec1)
{
    int i;
    int len;
    int j;
    j=0;
    len=Vec1.num();
    for(i=0;i<len;i++)
        if(Vec1.item(i)==2) j++;
    return j;
}
threeVector & threeVector::operator=(threeVector & rhs)
{
    if(this==&rhs)
        return *this;
    *mass=rhs.item(0);
    return *this;
}
int & threeVector::operator[](int i)
{
  if ((i>=0) && (i<count)) return mass[i];
  else {cout << "Error in vector::item"; return mass[0];}
}
threeVector threeVector::operator*(threeVector &rhs)
{
    int i;
    threeVector Vec(count);
    for(i=0;i<count;i++)
    {
        if(mass[i]<=rhs.item(i)) Vec.SetKomp(mass[i],i);
        else Vec.SetKomp(rhs.item(i),i);
        return Vec;
    }
}
void threeVector::SetKomp(int x,int i)
{
    mass[i]=x;
}
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    threeVector V1(2),V2(2),V3(2);
    int i;
    V1[0]=1;
    V1[1]=0;
    V2[0]=2;
    V2[1]=1;
    V3=V1*V2;
}
6 ответов

Shepard90

Много чего не так.
Vector::Vector(int i)
{ int j;
  count=i;
  int *mass=new int[count]; // объявляете(!) новую(!) переменную 
                                      // mass, перекрывающую поле класса
                                      // ничего не инициализируется.
  for (j=0; j<count; j++)
  {
          mass[j]=0;
  }
  cout << "vector created " << count << "\n";
}
threeVector::threeVector(threeVector &rhs) //коструктор-копировщик
{
        int *mass=new int[count]; // то же самое.
        *mass=rhs.item(0);  // только один элемент будет скопирован
}
threeVector threeVector::operator*(threeVector &rhs)
{
        int i;
        threeVector Vec(count);
        for(i=0;i<count;i++)
        {
                if(mass[i]<=rhs.item(i)) Vec.SetKomp(mass[i],i);
                else Vec.SetKomp(rhs.item(i),i);
                return Vec;  // возвратит значение после первого же прохода цикла
        }
}
Чтобы вот это сработало,
V3=V1*V2;
нужен еще оператор присваивания. Не забудьте проверить, что не присваиваете самого себя!
threeVector::threeVector(int *arr, int n):Vector(n)//конструктор
{
        *mass=*arr; // копируете только один, самый первый интеджер?!
         cout << "threeVector created " << count << "\n";
}
Посмотрите вот такой пример. Это хоть и шаблон класса, много лишних для вас методов, но тут есть примеры конструкторов, операторов, деструкторов.
#include <iostream>
 
using namespace std;
 
template <class _Tp>
class Vector
{
public:
        typedef _Tp value_type;
        typedef value_type* pointer;
protected:
        pointer* _data_start;
        pointer* _data_finish;
        pointer* _data_end_of_storage;
 
        void quickSort(int left, int right, bool (*compare)(const _Tp&, const _Tp&))
        {
                int i = left, j = right;
                value_type pivot = at((left + right) / 2);
 
                /* partition */
                while (i <= j)
                {
                        while (compare(at(i), pivot))
                                i++;
                        while (compare(pivot, at(j)))
                                j--;
                        if (i <= j)
                        {
                                pointer tmp = _data_start[i];
                                _data_start[i] = _data_start[j];
                                _data_start[j] = tmp;
                                i++;
                                j--;
                        }
                };
 
                /* recursion */
                if (left < j)
                        quickSort(left, j, compare);
                if (i < right)
                        quickSort(i, right, compare);
}
 
 
 
public:
        Vector(int n, unsigned int max_capacity = 0) : _data_start(0), _data_finish(0), _data_end_of_storage(0)
        {
                if (n > max_capacity)
                        max_capacity = n+1;
                _data_start = new pointer[max_capacity];
                _data_finish = _data_start + n;
                _data_end_of_storage =_data_start + max_capacity;
 
                for (int i = 0; i<size(); i++)
                        _data_start[i] = new value_type;
        }
        Vector(void) : _data_start(new pointer[1]), _data_finish(_data_start), _data_end_of_storage(_data_start+1) {}
        Vector(const Vector<_Tp>& other)
        {
                _data_start = new pointer[other.capacity()];
                _data_finish = _data_start + other.size();
                _data_end_of_storage =_data_start + other.capacity();
 
                for (int i = 0; i<size(); i++)
                        _data_start[i] = new value_type(other[i]);
        }
 
        value_type& push_back(const value_type value)
        {
                if (!(_data_finish < _data_end_of_storage))
                        reserve(capacity()+2);
                *_data_finish = new value_type(value);
                _data_finish++;
        }
 
        void sort(bool (*compare)(const _Tp&, const _Tp&))
        {
                quickSort(0, size()-1, compare);
        }
 
        void reserve(int new_capacity)
        {
                pointer* _new_data_start = new pointer[new_capacity];
                int new_size = (size()>new_capacity)?new_capacity:size();
 
                for (int i = 0; i<new_size; i++)
                        _new_data_start[i] = _data_start[i];
 
                delete [] _data_start;
 
                _data_start = _new_data_start;
                _data_finish = _data_start + new_size;
                _data_end_of_storage = _new_data_start + new_capacity;
        }
 
        Vector<_Tp> operator= (const Vector<_Tp>& other)
        {
                if (this!=&other)
                {
                        if (_data_start!=0)
                                delete _data_start;
                        _data_start = new pointer[other.capacity()];
                        _data_finish = _data_start + other.size();
                        _data_end_of_storage =_data_start + other.capacity();
 
                        for (int i = 0; i<size(); i++)
                                _data_start[i] = new value_type(other[i]);
                }
                return *this;
        }
 
        value_type& operator[](unsigned int n) const { return *(_data_start[n]); }
        value_type& operator[](unsigned int n) { return *(_data_start[n]); }
 
        value_type& at(int n) const { return *(_data_start[n]); }
        value_type& at(int n) { return *(_data_start[n]); }
 
        unsigned int size() const { return (_data_finish - _data_start); }
        unsigned int capacity() const { return (_data_end_of_storage - _data_start); }
 
        ~Vector()
        {
                for (int i=0; i<size(); i++)
                        delete _data_start[i];
                delete [] _data_start;
        }
};


Shepard90

Да тут все практически без изменений.
// Laba7.cpp : Defines the entry point for the console application.
//
 
#include "stdafx.h"
#include "stdio.h"
#include "conio.h"
#include <iostream>
using namespace std;
 
class Vector
{
protected:
  int *mass; // указатель на начало вектора
  int count; // количество элементов в векторе
 public:
  Vector();
  Vector(int i); // конструктор (назначен параметр по умолчанию)
  ~Vector(); // деструтор (не может иметь параметров)
 int item(int i) const; // возвращает указанный элемент
  void  assign(int i, int x); // назначение элемента
  int num(); // возвращает число элементов (inline)
  int norm(); // возвращает квадрат нормы вектора
};
 
Vector::Vector()
{
    count=2;// двойка здесь присвоена для того, чтобы программа, в ходе исправления, выполнялась без ошибок.
}
Vector::Vector(int i)
{ int j;
  count=i;
  mass=new int[count];
  for (j=0; j<count; j++)
  {
      mass[j]=0;
  }
  cout << "vector created " << count << "\n";
}
 
Vector::~Vector()
{
 delete mass;
 cout << "vector destroyed\n";
}
 
int Vector::item(int i) const
{  if ((i>=0) && (i<count)) return *(mass+i);
  else {cout << "Error in vector::item"; return 0;}
}
 
void Vector::assign(int i, int x)
{
  if ((i>=0) && (i<count))  *(mass+i)=x;
  else cout << "Error in vector::assign";
}
int Vector::num() 
      { return count; }
int Vector::norm()
{ int i;
  int x=0;
  for (i=0; i<count; i++) x+=mass[i]*mass[i];
  return x;
}
 
 
class threeVector: public Vector
{
public:
    threeVector();//конструктор без параметрров
    threeVector(int *arr, int n);//передаю указатель на массив и длину массива
    threeVector(int n);//только длину
    ~threeVector();//деструктор
    threeVector(threeVector &rhs);//конструктор-копировщик
    void OrtVectors(threeVector Vec1, threeVector Vec2);//проверка на ортогональность
    int SearchKomp();// поиск компонента вектора
    threeVector & operator=(threeVector &rhs);
    int & operator[](int i);
    threeVector  operator*(threeVector &rhs);
    void SetKomp(int x,int i);
};
threeVector::threeVector():Vector()//конструктор
{
    int j;
  count=1;
  mass=new int[count];
  for (j=0; j<count; j++) *(mass+j)=0;
  cout << "threeVector created " << count << "\n";
}
threeVector::threeVector(int *arr, int n):Vector(n)//конструктор
{
     mass=arr;
     cout << "threeVector created " << count << "\n";
}
threeVector::threeVector(int n):Vector(n)//конструктор
{
    cout<<"threeVector created "<<count<<"\n";
}
threeVector::~threeVector()//деструктор
{
    cout<<"threeVector destroed\n";
}
threeVector::threeVector(threeVector &rhs) //коструктор-копировщик
{
    int i;
    mass=new int[count];
    for(i=0;i<count;i++)
    {
        mass[i]=rhs.item(i);
        
    }
 
}
void threeVector::OrtVectors(threeVector Vec1, threeVector Vec2)
{
    int i;
    int len;
    if(Vec1.num()<Vec2.num())
    {len=Vec1.num(); }
    else 
    {len=Vec2.num();}
    for(i=0;i<len;i++)
    {
        if(Vec1.item(i)==0 && Vec2.item(i)==1 || Vec1.item(i)==1 && Vec1.item(i)==0) 
        {
            printf("Vectors ortogonal\n");
            break;
        }
        else
        {
            if(i==len-1) printf("Vectors not ortogonal\n");
        }
    }
        
}
 
int threeVector::SearchKomp()
{
    int i;
    int len;
    int j;
    j=0;
    len=count;
    for(i=0;i<len;i++)
        if(mass[i]==2) j++;
    return j;
}
threeVector & threeVector::operator=(threeVector & rhs)
{
    if(this==&rhs)
        return *this;
    *mass=rhs.item(0);
    return *this;
}
int & threeVector::operator[](int i)
{
  if ((i>=0) && (i<count)) return mass[i];
  else {cout << "Error in vector::item"; return mass[0];}
}
threeVector threeVector::operator*(threeVector &rhs)
{
    int i;
    threeVector Vec(count);
    for(i=0;i<count;i++)
    {
        if(mass[i]<=rhs.item(i))
        {
            Vec.SetKomp(mass[i],i);
        }
        else
        {
            Vec.SetKomp(rhs.item(i),i);
        }
    }
    return Vec;
}
void threeVector::SetKomp(int x,int i)
{
    mass[i]=x;
}
 
 
 
int _tmain(int argc, _TCHAR* argv[])
{
    threeVector V1(2),V2(2),V3(2);
    V1[0]=2;
    V1[1]=0;
    V2[0]=2;
    V2[1]=2;
    V3=V1*V2;
    cout<<V1[0]<<endl;
    cout<<V1[1]<<endl;
    cout<<V2[0]<<endl;
    cout<<V2[1]<<endl;
    cout<<V3[0]<<endl;
    cout<<V3[1]<<endl;
    V1.OrtVectors(V1,V2);
    cout<<"kolvo komponent ravnih 2: "<<V2.SearchKomp()<<endl;
    _getch();
}


Shepard90

Vector::Vector()
{
        count=2;// двойка здесь присвоена для того, чтобы программа, в ходе исправления, выполнялась без ошибок.
}
Хитро грабли разложили. Будет трудно отыскать.
Vector A;
cout << A.num(); // сразу два значения в векторе?
cout << assign(1, 1);  // а если туда записать чего-нибудь?
                        // упало...
threeVector::threeVector(int *arr, int n):Vector(n)//конструктор
{
         mass=arr; // копируется только указатель, значения не копируются
         cout << "threeVector created " << count << "\n";
}
threeVector & threeVector::operator=(threeVector & rhs)
{
        if(this==&rhs)
                return *this;
        *mass=rhs.item(0); // данные не копируются, если присваеваемый объект 
                                   // будет удален, mass будет указывать в нераспределенную
                                   // область памяти
        return *this;
}
Далее, для решения вашей задачи, вам нужно убрать vector::operator[], он всю малину попортит, в этом операторе нельзя проверять присваиваемое выражение.
void threeVector::SetKomp(int x,int i)
{
        // Тут организуйте проверку на значение x.
        mass[i]=x;
}


Shepard90

threeVector::threeVector(int *arr, int n):Vector(n)//конструктор { mass=arr; // копируется только указатель, значения не копируются cout << "threeVector created " << count << "\n" ; }
думаю этого достаточно. Он все равно нигде не используется. Просто по заданию должен быть. Препод молодец конечно - расписал все по пунктикам. Никакого творчества!
threeVector & threeVector::operator=(threeVector & rhs)
{
    int i;
    if(this==&rhs)
        return *this;
    for(i=0;i<count;i++)
        mass[i]=rhs.item(i);
    return *this;
}
Кажись так покатит.lemegeton, а по поводу конструктора баз класса запускающего ни с того ни с сего? Ты причину не распознал?


Shepard90

Мне, к сожалению, нечем трассировать. У меня только gcc.


Shepard90

Ну да ладно. Все равно очень помог!