Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Для новичков > Перегрузка операторов. [VS C++]


Автор: Macbeth 31.3.2010, 20:42
Здравствуйте.
Задание:
Описать класс, 3 объекта, используя разные конструкторы; объект №3 увеличить в раза(operator*), удвоением каждого символа("abc" ---> "aabbcc"); сложить(operator+) объекты № 3 и №2, затем присвоить(operator=) это объекту №1.

Вот такой код сейчас. Выбивает ошибку, когда инициализирую объект L3.
"illegal, left operand has type Row * "
"illegal, right operand has type Row* "
Очень прошу помочь исправить.

Код

#include "stdafx.h"
#include "row.h"
#include <iostream>
#include <string>
using namespace std;
const int n = 2;

class Row
{
    private:
        char *data;
        
    public:
        Row();
        Row(char* v);
        Row(Row &);
        
        Row* operator*(Row *c);
        Row* operator+(Row *c);
        Row* operator=(Row *h);

        int Dimension();
        void Out();
};
/**************************/
Row::Row()
{
    data = NULL;
}

Row::Row(char* v)
{
    data = v;
}

Row::Row(Row &copy)
{
    data = copy.data;
}

int Row::Dimension()
{
    int res0 = strlen(data);
    return res0;
}

void Row::Out()
{
    cout << "stroka: " << data << endl;
}

Row* Row::operator*(Row *c)
{    
    char *tmp = new char[strlen(data)];
    tmp = data;
    
    int len = strlen(data);
    for(int i = 0; i < len; i++)
    {
        for(int j = 0; j < n; j++)
        {
            tmp[i*n*j] = data[j];
        }
    }
    
    Row *res = new Row(tmp);
    return res;
}

Row* Row::operator+(Row *c)
{
    int len = strlen(data);
    char *tmp = new char[len+1];
    strcpy(tmp,data);
    strcat(tmp,c->data);

    Row *res1 = new Row(tmp);
    return res1;
}

Row* Row::operator=(Row *h)
{
    Row* res3 = new Row(h->data);
    //res3 = h;
    return res3;
}

#include "stdafx.h"
#include "row.h"
#include <iostream>
#include <string>
/**********************/
void main()
{
    Row* L3 = new Row("abc");
    Row* L2(L3);

    Row L1 = (L3*L3) + L2;    //       !здесь ошибка!

    L3->Out();
    cout << "Dlinna L3: " << L2->Dimension() << endl;

    L1.Out();
    cout << "Dlinna L1: " << L1.Dimension() << endl;    
}

Автор: smalcom 31.3.2010, 23:30
Товарищи у вас на всех одна лаба чтоли? Хоть бы именна переменных поменяли.

Цитата

Вот такой код сейчас. Выбивает ошибку, когда инициализирую объект L3.

Где выбивает догадаться надо?

Автор: Macbeth 31.3.2010, 23:38
Ошибся. Когда иниц. L1. Вот здесь(4 строка в main):
Код

Row L1 = (L3*L3) + L2;


Немного разобрался, здесь должно быть что-то вроде:
Row L1 = (*L3)*(*L3) + L2;

* - между объектами L3 - произведение, остальное указатели(не знаю как по другому описать)

Автор: jonie 1.4.2010, 08:38
L2 у вас тоже указатель, тоже надо разыменовывать....

Автор: xvr 1.4.2010, 15:09
В коде куча ошибок - в строках 38, 54, 55, 62, 73
Операторы (в строках 18-20) заданны не правильно (они должны принимать const Row& и возвращать Row)
Оператор * вообще задан неправильно - он должен умножать на int, а не на Row

Автор: Macbeth 1.4.2010, 16:45
Можно поподробнее о ошибке в конструкторе копирования и операторе * ?

Заменил указатели ссылками, ошибки в размерах строчных массивов исправил.
Код

#include "stdafx.h"
#include <string>
#include "string.h"
#include <iostream>
using namespace std;


class String 
{
private:
    char* s;

public:
    String();
    String(char* v);
    String(String &d);
    ~String();

    int StrLength();
    void StrShow();

    String& operator*(const String& s1)const;
    String& operator+(const String& s1)const;
    String& operator=(const String& h);
};
/***********************************/
String::String()
{
    s = NULL;
}

String::String(char *v)
{
    s = v;
}

String::String(String &d)
{
    s = d.s;
}

String::~String(){}

int String::StrLength()
{
    int res = strlen(s);
    return res;
}

void String::StrShow()
{
    std::cout << "stroka: " << s << endl;
}

String& String::operator *(const String& s1)const
{
    int len = strlen(s);
    char* tmp = new char[(strlen(s)*2)+1];
        char* t = new char[strlen(s)+1];

    for(int i = 0; i < strlen(s); i++)
    {
        tmp[i*2+1] = tmp[i*2] = t[i];
    }
    String newStr(tmp);

    delete tmp;
    return newStr;
}

String& String::operator+(const String& s1)const
{
    int len = strlen(s);
    char* tmp = new char[strlen(s1.s) + strlen(s) + 1];  
    strcpy(tmp, s);
    strcat(tmp, s1.s);

    String newStr(tmp);

    delete tmp;
    return newStr;
}

String& String::operator=(const String& h)
{
    String res;
    res = h.s;
    return res;
}
/*************************************/
int _tmain(int argc, _TCHAR* argv[])
{
    String s1 = "abc";
    String s2(s1);
    String s3 = (s1*s1) + s2;

    s1.StrShow();
    cout << "length s1: " << s1.StrLength() << endl;

    //s3.StrShow();
    //cout << "length s3: " << s3.StrLength() << endl;

    return 0;
}


При отладке в цикле где я удваиваю строку выбивает ошибку "Unhandled exception at 0x00412312". Что там не так?

Автор: ИванМ 1.4.2010, 16:49
Цитата(Macbeth @  1.4.2010,  16:45 Найти цитируемый пост)
String& String::operator *(const String& s1)const
{
    int len = strlen(s);
    char* tmp = new char[(strlen(s)*2)+1];
        char* t = new char[strlen(s)+1];
    for(int i = 0; i < strlen(s); i++)
    {
        tmp[i*2+1] = tmp[i*2] = t[i];
    }
    String newStr(tmp);
    delete tmp;
    return newStr;
}

ломал голову так и не понял что этот оператор должен был сделать. присваивание неициализированных (случайных) значений аналогичным.
и в названии параметра s1, а работаете с s

Автор: Macbeth 1.4.2010, 17:01
Строку (объект1) нужно удвоить и склеить с объект2 (инициализируется конструктором копирования - присваивается изначальное значение объект1, т.е. "abc" .
Насчет параметра, Вы имеете ввиду сделать так 
Код
 s1.s 
?

Автор: ИванМ 1.4.2010, 17:41
Цитата(Macbeth @  1.4.2010,  17:01 Найти цитируемый пост)
Строку (объект1) нужно удвоить и склеить с объект2

это все в одном операторе * или это такая задача вообще?

Цитата(Macbeth @  1.4.2010,  17:01 Найти цитируемый пост)
Насчет параметра, Вы имеете ввиду сделать так 
Выделить всёкод C++
1:
    
 s1.s 

я имею ввиду, что надо писать просто s1, а не s, коли вы пишете так: (const String& s1)

Автор: Macbeth 1.4.2010, 17:52
Цитата(ИванМ @  1.4.2010,  17:41 Найти цитируемый пост)
это все в одном операторе * или это такая задача вообще?

s3 = (s1*s1) + s2. Удвоение надо реализовать перегрузкой оператора * . Склеить перегрузкой оператора + .
Цитата(ИванМ @  1.4.2010,  17:41 Найти цитируемый пост)
я имею ввиду, что надо писать просто s1, а не s, коли вы пишете так: (const String& s1)

Как же мне тогда инициализировать массив, для работы в цикле? (кстати, я забыл его скопировать сюда: t = s1.s) В  s  хранится строка.

Автор: ИванМ 1.4.2010, 17:57
Цитата(Macbeth @  1.4.2010,  17:52 Найти цитируемый пост)
s3 = (s1*s1) + s2.

сомневаюсь что так
по идеи должно быть s3 = (s1*2) + s2
s1 это объект String. У него нет метода s. Не понимаю о чем вы говорите

Автор: Macbeth 1.4.2010, 18:17
Цитата(ИванМ @  1.4.2010,  17:57 Найти цитируемый пост)
s1 это объект String. У него нет метода s. Не понимаю о чем вы говорите 

Разве так нельзя обращаться к private части?

Автор: ИванМ 1.4.2010, 18:22
Цитата(Macbeth @  1.4.2010,  18:17 Найти цитируемый пост)
Разве так нельзя обращаться к private части? 

к private части можно обращаться только из этого же класса, и в private части класса AnsiString такого члена (s) тоже нет

Автор: Macbeth 1.4.2010, 18:42
Я наверное чего-то не понимаю. Причем тут AnsiString? И вроде бы я из того же класса обращаюсь к  s.

Автор: ИванМ 1.4.2010, 18:47
прошу прощения
я вас дезинформировал
я думал String это не ваш класс а стандартный
почему то думал что вы работаете внутри Row

Добавлено @ 19:00
вот например, код набросал для утроения строки из 4 символов:
ins - входной массив, outs-выходной

Код

    char ins[5]="1234";
    char outs[13];
    int n=3;
    for(int i=0;i<strlen(ins);i++)
    for(int j=0;j<n;j++)
    {
        outs[i*n+j]=ins[i];
    }
    outs[12]=0;


для удвоения просто заменить n с 3 на 2

Автор: xvr 1.4.2010, 20:26
Цитата(Macbeth @ 1.4.2010,  16:45)
Можно поподробнее о ошибке в конструкторе копирования и операторе * ?

Можно. Коментарии в тексте

Код


class String 
{

    String& operator*(const String& s1)const;
    String& operator+(const String& s1)const;
    String& operator=(const String& h);
// Методы должны возвращать String, а не String&

};

String::String(char *v)
{
    s = v;
// Ошибка - строку нужно копировать, так например
   strcpy(s=new char[strlen(v)+1],v);
}

String::String(String &d)
{
    s = d.s;
// Аналогично
   strcpy(s=new char[strlen(d.s)+1],d.s);

}

String::~String()
{
// Ошибка - отсуствует удаление выделенной памяти:
 delete[] s;
}

String& String::operator *(const String& s1)const
{
    int len = strlen(s);
    char* tmp = new char[(strlen(s)*2)+1];
        char* t = new char[strlen(s)+1];
// Это зачем ????

    for(int i = 0; i < strlen(s); i++)
    {
        tmp[i*2+1] = tmp[i*2] = t[i];
// t не проинициализирован, нужно s[i]
    }
    String newStr(tmp);

    delete tmp;
    return newStr;
}

String& String::operator=(const String& h)
{
    String res;
    res = h.s;
// 2 ошибки - нет копирования строки, и бесконечная рекурсия (res = h.s; развернется в res.operator=(String(h.s)); )
    return res;
}
Вопрос - зачем оператору '*' второй параметр, если он его игнорирует?

Автор: Macbeth 1.4.2010, 23:40
Взял код http://forum.vingrad.ru/index.php?showtopic=99006&view=findpost&p=752829 Добавил только свою перегрузку оператора * . 
Есть ли ошибки? Компилятор ругается уже в процессе компиляции.

Код

#include "stdafx.h"
#include <stdio.h>
#include <iostream>   
#include <conio.h>
#include <string>
#include <mbstring.h>
#pragma hdrstop
using namespace std;
//---------------------------------------------------------------------------
#pragma argsused
class String2 
{
public:
  char* s;       
  String2();
  String2(char *c); 
  String2(const String2 &d);
  ~String2();

  String2 operator+(const String2 & s1)const;
  String2 operator*(const String2 & s1)const;
  String2 operator = ( String2 & s33 );
};

String2::String2( char *c ) 
  {
      int len = strlen(c);
      strcpy(s = new char[len+1],c);
  }

String2::String2(const String2 &d)
  {
      int len = strlen(d.s);
      strcpy(s = new char[len+1],d.s);
  }

String2::~String2()
  { 
      delete[] s; 
  }

String2  String2::operator+(const String2 &s1)const
{
  char *s22 = new char[strlen(s1.s)+strlen(this->s)+1]; 
  strcpy(s22,this->s);
  strcat(s22, s1.s);
  String2 *newStr = new String2(s22);// 
  delete s22;
  return *newStr;                       
}

String2 String2::operator*(const String2 &s1)const
{
    int len = strlen(s1.s);
    const int n = 2;
    char* tmp = new char[(len*n)+1];
    tmp = NULL;
    //char* t = new char[len+1];
    //t = NULL;
    //t = s1.s;

    for(int i = 0; i < len; i++)
    {
        for(int j = 0; j < n; j++)
        {
            tmp[i*n+j] = s[i];
        }
    }
    String2* newStr = new String2(tmp);

    delete tmp;
    return *newStr;
}

String2  String2::operator= ( String2 & s33 )
{
   strcpy(s,s33.s);
   return *this;
}
int main(int argc, char* argv[]) 
{
  String2 s1="abc";
  String2 s2(s1);
  //s2=s1;
  String2 s3=(s1*s1)+s2;
  cout<<s3.s;        
  //getch();
  cin.get();
  return 0;
}

Автор: xvr 2.4.2010, 06:50
Цитата(Macbeth @ 1.4.2010,  23:40)
Взял код http://forum.vingrad.ru/index.php?showtopic=99006&view=findpost&p=752829 Добавил только свою перегрузку оператора * . 
Есть ли ошибки? 

Есть
Цитата

Компилятор ругается уже в процессе компиляции.
Где именно?

Ошибки -
Код

class String2 
{
public:
  char* s;       
// Это лучше внести в private часть
  String2();
  String2(char *c); 
  String2(const String2 &d);
  ~String2();

  String2 operator+(const String2 & s1)const;
  String2 operator*(const String2 & s1)const;
  String2 operator = ( String2 & s33 );
};

String2::String2( char *c ) 
// Должно быть String2::String2( const char *c ) (и в теле класса тоже)

String2  String2::operator+(const String2 &s1)const
{
  char *s22 = new char[strlen(s1.s)+strlen(this->s)+1]; 
  strcpy(s22,this->s);
  strcat(s22, s1.s);
// Это не правильно - будет утечка памяти
  String2 *newStr = new String2(s22);// 
  delete s22;
  return *newStr;                       
// Надо так -
  String2 newStr(s22);// 
  delete s22;
  return newStr;                        
}

String2 String2::operator*(const String2 &s1)const
{
    int len = strlen(s1.s);
    const int n = 2;
    char* tmp = new char[(len*n)+1];
    tmp = NULL;
    //char* t = new char[len+1];
    //t = NULL;
    //t = s1.s;

    for(int i = 0; i < len; i++)
    {
        for(int j = 0; j < n; j++)
        {
            tmp[i*n+j] = s[i];
        }
    }
// Не прописан завершающий нуль в tmp[len*n]=0;

    String2* newStr = new String2(tmp);
    delete tmp;
    return *newStr;
// Аналогично предыдущему месту
}

String2  String2::operator= ( String2 & s33 )
{
   strcpy(s,s33.s);
// Не правильно - не выделенна память под s. Надо удалить память от старой строки и создать новый
   return *this;
}


Автор: Macbeth 2.4.2010, 07:53
Цитата(xvr @  2.4.2010,  06:50 Найти цитируемый пост)
Где именно?

В цикле, где удваиваю строку.

Цитата(xvr @  2.4.2010,  06:50 Найти цитируемый пост)
Не правильно - не выделенна память под s. Надо удалить память от старой строки и создать новый

Т.е. записать предыдущую строку в какой-нибудь темп, удалить строку, опять распределить память и записать темп?

Автор: xvr 2.4.2010, 10:26
Цитата(Macbeth @ 2.4.2010,  07:53)
Цитата(xvr @  2.4.2010,  06:50 Найти цитируемый пост)
Где именно?

В цикле, где удваиваю строку.

Конкретный номер строки (по листигу из предыдущего поста) и текст ошибки от компилятора - телепаты в отпуске  smile 

Цитата

Т.е. записать предыдущую строку в какой-нибудь темп, удалить строку

- Можно выбросить старую переписку 5 годовой давности?
- Можно, но перед тем, как выбростиь, обязательно разложите ее по адресатам и датам.
 smile 

Код

String2&  String2::operator= ( String2 & s33 )
{
  delete[] s; 
  strcpy(s=new char[strlen(s33.s)+1],s33.s);
  return *this;
}

Автор: Macbeth 2.4.2010, 11:55
Цитата(xvr @  2.4.2010,  10:26 Найти цитируемый пост)
Конкретный номер строки (по листигу из предыдущего поста) и текст ошибки от компилятора

#48 - "Unhandled exception at 0x00412312"

upd. хм, отредактировал код, теперь в strlen.asm: "Unhandled exception at 0x1026f8e0 (msvcr90d.dll) in VALERON.exe: 0xC0000005: Access violation reading location 0xcccccccc" в строке: 
main_loop:
        mov     eax,dword ptr [ecx] // здесь

Автор: xvr 2.4.2010, 13:26
Вот эта конструкция вообще 'шедевр'
Код

    char* tmp = new char[(len*n)+1];
    tmp = NULL;

Цитата

#48 - "Unhandled exception at 0x00412312"
Это не ошибка при компиляции, а ошибка при выполнении.
Цитата

upd. хм, отредактировал код, теперь в strlen.asm: "Unhandled exception at 0x1026f8e0 (msvcr90d.dll) in VALERON.exe: 0xC0000005: Access violation reading location 0xcccccccc" в строке: 
main_loop:
        mov     eax,dword ptr [ecx] // здесь 
Попытка вызвать strlen от неинициализированного указателя. Посмотрите в стеке откуда звалась strlen

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