Я хочу расширить std :: string, но не по той причине, что вы думаете - PullRequest
3 голосов
/ 18 марта 2010

У меня есть метод, который эффективно принимает строку. Однако есть очень ограниченное подмножество строк, которые я хочу использовать. Я думал о типе определения std :: string как некоторый класс, и вызывать функции явным образом. Однако я не уверен, что это сработает. Идеи?

Ответы [ 3 ]

8 голосов
/ 18 марта 2010

Обычное правило по-прежнему применяется: класс не предназначен для наследования, и его деструктор не является виртуальным, поэтому, если вы когда-нибудь перейдете к базовому классу std :: string и позволите объекту быть уничтоженным, ваш деструктор производного класса не будет вызван.

Если вы можете гарантировать, что этого никогда не произойдет, продолжайте.

В противном случае вы можете сделать std::string членом вашего класса, а не базового класса. или вы могли бы использовать личное наследование. Проблема с этим подходом состоит в том, что вам пришлось бы повторно реализовать строковый интерфейс, чтобы класс можно было использовать как строку.

Или вы можете просто определить свой класс, чтобы предоставить функцию getString(), которая возвращает внутренний объект std::string. Тогда вы все равно можете передать свой собственный класс, и компилятор будет жаловаться, если вы попытаетесь передать std::string, но внутренняя строка доступна, когда вам это нужно. Это может быть лучшим компромиссом.

7 голосов
/ 18 марта 2010

Звучит так, как будто вы хотите ограничить ввод (т. Е. Возможно, строку, которая допускает только буквы).

Я бы порекомендовал использовать строку внутри класса и затем обернуть нужные функции.

class limited_string
{
    std::string str;

public:
    limited_string(const char *data)
        : str(data)
    {
        if (!valid(str))
            throw std::runtime_exception(); 
    }

    virtual ~limited_string() {}

    limited_string &operator+=(const char *data)
    {
        // do all your work on the side - this way you don't have to rollback
        // if the newly created string is invalid
        std::string newstr(str);
        newstr += data;
        if (!valid(newstr))
            throw std::runtime_exception();

        str = newstr;
    }

    virtual bool valid(const std::string str) = 0;
}
0 голосов
/ 19 марта 2010

Похоже, у вас есть один метод, который принимает ограниченную строку. Действительно ли нужен новый класс?

void needs_restricted_string( std::string const &str ) {
    if ( ! is_restricted_string( str ) ) throw std::runtime_error( "bad str" );
    …
}

В противном случае, единственное, что вы хотите захватить, это соответствие строки ограничениям. Единственное отличие, которое я вижу между is_restricted_string() и классом времени компиляции, - это производительность, если у вас есть структура хранения, выделенная для проверенных строк. Не преждевременно оптимизировать. Тем не менее, было бы также ошибкой добавлять слишком много функциональности в ваш новый класс или использовать его как строку.

class restricted_string {
    std::string storage;
public:
     // constructor may implement move or swap() semantics for performance
     // it throws if string is no good
     // not explicit, may be called for implicit conversion
    restricted_string( std::string const & ) throw runtime_error;
     // getter should perhaps be private with needs_restricted as friend
    std::string const &str() const { return storage; }
}; // and no more functionality than that!

void needs_restricted_string( restricted_string const &str ) {
    std::string const &known_restricted = str.str();
}

std::string mystr( "hello" );
needs_restricted_string( mystr );
...