Re[9]: Задолбало гццой
От: wander  
Дата: 12.12.09 22:10
Оценка:
Здравствуйте, MikelSV, Вы писали:

MSV>Кода много, не знаю, что именно показывать.


MSV>В данном случае единственный вариант реализации operator+ может быть:

MSV>HLString& operator+(const MString& string){...}
Это далеко не единственный вариант ошибочной реализации operator+ и подобных ему операторов.
MSV>Это строковый класс, он прибавляет текст у уже записанному в нем.
Суть operator+ в создании нового объекта посредством объединения двух имеющихся (конкатенации).
Возьмем например:
a = 2 + 2

Было бы маразмом полагать, что первое слагаемое после этого станет равным 4. Это две константы. Так какого, простите, перепуга вы ожидаете другого поведения с вашими строками? Если вы пишете
some_class1(5) + some_class2(4)

— это тоже самое. Поэтому,
во-первых, operator+, operator- и иже с ними никогда не должны возвращать ссылку, если только вы не хотите устроить себе грабли на ровном месте.
во-вторых, семантика описанного вами оператора соответствует operator+=, вот он, да, он возвращает ссылку, только это совсем другая песня.
в-третьих, функция operator+ должна быть свободной. Во избежание неожиданных эксцессов в вариантах с перестановкой слагаемых.
Итого:
my_string operator+(my_string const & a, other_string const & b) // const, ибо мы не изменяем слагаемые, мы формируем из них результат
{
    my_string result(a.size() + b.size());
    // операции по объединению строк
    return result; // в результате my_string, ибо мы прибавляем к ней
}

other_string operator+(other_string const & a, my_string const & b) // const, ибо мы не изменяем слагаемые, мы формируем из них результат
{
    other_string result(a.size() + b.size());
    // операции по объединению строк
    return result; // в результате other_string, ибо мы прибавляем к ней
}

other_string const & res = other_string("bla-bla") + my_string("bla-bla"); // будет работать
other_string res = other_string("bla-bla") + my_string("bla-bla"); // будет работать

my_string const & res = my_string("bla-bla") + other_string("bla-bla"); // ок
my_string res = my_string("bla-bla") + other_string("bla-bla"); // ок

my_string & res = my_string("bla-bla") + other_string("bla-bla"); // бамс, ошибка!

Я заметил, что вы пропускаете мимо ушей все что я пишу. Поэтому советую вам обратиться в главу 11 — Перегрузка Операторов, русского издания книги Б. Страуструпа "Язык программирование С++. 3е издание", для вдумчивого чтения и подтверждения всего, что я выше написал.

MSV>Собственно тут все просто, класс собирает текст в строку и возвращает ее через operator MString().

Вы правы, все очень просто. Можно например посмотреть реализацию такого же механизма в библиотеке QT. Добавлю, что если придерживаться правил, которые я описал выше оператор приведения вам и вовсе не понадобится.

MSV>Кстати этот код работает:

MSV>Drawn((HLString()+"Uncnown command '"+comm+"'\r\n\r\n").operator MString());
MSV>Но я за то, чтобы компилятор сам догадывался о типах и не нужно было дописывать .operator MString().

Теперь к вашим баранам, откройте для себя mutable:
class MString;

class HLString
{
public:
    HLString()
    {}
    HLString(char const * str)
        : buf_(str)
    {}
    HLString const & add(char const * str) const
    {
        buf_ += str;
        return *this;
    }
    HLString const & add(HLString const & str) const
    {
        buf_ += str.data();
        return *this;
    }
    std::string const & data() const
    {
        return buf_;
    }
    HLString const & add(MString const & str) const;
private:
    // для буфера использовал стандартную строку, здесь показана только суть
    mutable std::string buf_; // mutable позволит менять данные в константных объектах
};


class MString
{
public:
    MString()
    {}
    MString(char const * str)
        : buf_(str)
    {}
    MString const & add(char const * str) const
    {
        buf_ += str;
        return *this;
    }
    MString const & add(MString const & str) const
    {
        buf_ += str.data();
        return *this;
    }
    std::string const & data() const
    {
        return buf_;
    }
    MString const & add(HLString const & str) const;

private:
    // для буфера использовал стандартную строку, здесь показана только суть
    mutable std::string buf_; // mutable позволит менять данные в константных объектах
};


MString const & MString::add(HLString const & str) const
{
    buf_ += str.data();
    return *this;
}

HLString const & HLString::add(MString const & str) const
{
    buf_ += str.data();
    return *this;
}

void Drawn(MString const & a)
{
    std::cout << a.data() << std::endl;
}

int main()
{
    HLString comm("test");

    Drawn(MString().add("Unknown command '").add(comm).add("'\r\n\r\n"));

    return 0;
}


MSV>Варианты для гцц также мучил в студии. Все нормально понимаются. Жесткое следование стандартам — зло.


Зло — это нарушение стандартов студией. Если бы язык был в ней правильно реализован с самого начала, то всего этого бардака не было бы.
Ведь все это сделано не просто так, а потому что иначе — нелогично. Пример с оператором+ ясно это показывает.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.