Доступ к строковому классу с помощью оператора [] - PullRequest
1 голос
/ 18 февраля 2012

Для обучения я пытаюсь написать класс, такой как std :: string. Я прочитал, что метод в (int) возвращает ссылку на символ и выдает исключение в случае, если индекс неверен (слишком длинный или отрицательный). Оператор [] вместо этого не выдает никаких исключений. Но так как он возвращает ссылку, если индекс слишком длинный, что он возвращает? Это у меня класс:

class string
{
    public:
    static const unsigned int length_max=100;
    string(const char* field=NULL)
    {
        if(field!=NULL)
        {
            const unsigned int length=strlen(field);
            this->field=new char[length+1];
            this->length=length;
            for(unsigned int i=0;i<=length;i++)
                this->field[i]=field[i];
        }
        else
        {
            this->field=NULL;
            length=0;
        }
    }
    string& operator=(const char* field)
    {
        const unsigned int length=strlen(field);
        if(this->field!=NULL)
            delete this->field;
        this->field=new char[length];
        this->length=length;
        for(unsigned int i=0;i<length;i++)
            this->field[i]=field[i];
        return *this;
    }
    string& operator= (const string& str)
    {
        *this=str.field;
        return *this;
    }
    operator char* ()
    {
        return field;
    }
    friend std::ostream& operator<< (std::ostream& out, string& str);
    friend std::istream& operator>> (std::istream& in, string& str);
    private:
    char* field;
    unsigned int length;
};

std::ostream& operator<<(std::ostream& out, string& str)
{
    out << str.field;
    return out;
}

std::istream& operator>> (std::istream& in, string& str)
{
    char temp[string::length_max];
    in >> temp;
    str=temp;
    return in;
}

Я хочу сделать оператор [], я также мог бы заставить его выдать исключение, но проблема в том, что я не знаю, что он вернет в случае, если индекс слишком длинный. Например, перегрузка оператора [] такова:

    char& operator[] (int i)
    {
        try
        {
            if(i<0 || i>=length)
                throw indexException();
            return field[i];
        }
        catch(indexException& e)
        {
            std::cerr << e.what() << std::endl;
        }
    }

Это исключение:

class indexException:std::exception
{
    public:
    virtual const char* what()
    {
        return "Index is either too long, or negative";
    }
};

Он должен возвращать ссылку на символ, а не только символ, потому что я хочу сделать его назначаемым, поэтому, например, если у меня есть строка str, я мог бы сказать str [5] = 'c'. Я также хочу обработать исключение и не выходить из программы с помощью exit (). Поэтому, если есть исключение, оно не возвращает никакого значения, строка также может быть пустой. Что я должен вернуть? Я хотел бы сделать его похожим на std :: string, но я не очень хорошо понял, как реализован один из std :: string.

1 Ответ

2 голосов
/ 18 февраля 2012

Нет особого смысла создавать исключение, если вы собираетесь поймать его в том же блоке. Просто управляйте оператором if, если хотите что-то вернуть, вместо того, чтобы выдавать ошибку за пределы вашей функции.

Стандартный строковый класс не выполняет никаких проверок своего индекса, поэтому нет дополнительных затрат. Если индекс выходит за границы, вы получаете неопределенное поведение, потому что вы используете индекс вне границ во внутреннем буфере.

Вы можете выбрать все, что хотите возвращать за пределы индексов. Ноль был бы хорошим выбором, так как это указывало бы на конец строки в стиле C.

...