Как мне получить доступ к переменным-членам в классе строки STL? - PullRequest
8 голосов
/ 24 декабря 2011

Я работаю над одной из задач программирования в книге «Начиная с ранних объектов C ++, 7-е издание», и одно из заданий просит создать класс, производный от строкового класса STL.Я отправляю вопрос с целью понять, что мне разрешено делать и как я должен реализовывать решение, чтобы никто не предлагал более продвинутые предложения.

- Вопрос, как написано втекст -

Тестирование палиндрома

Палиндром - это строка, которая читается так же, как и вперед.Например, слова мама, папа , мадам и радар являются палиндромами.Напишите class Pstring, который получен из STL string class.Pstring class добавляет функцию-член

bool isPalindrome()

, которая определяет, является ли строка палиндромом.Включите конструктор, который принимает объект STL string в качестве параметра и передает его конструктору базового класса строки.Протестируйте свой класс, используя основную программу, которая просит пользователя ввести строку.Программа использует строку для инициализации объекта Pstring, а затем вызывает isPalindrome (), чтобы определить, является ли введенная строка палиндромом.

Может оказаться полезным использовать оператор индекса [] строкового класса: ifstr - строковый объект, а k - целое число, тогда str [k] возвращает символ в позиции k в строке.

- End -

Мой главный вопрос: как сделатьЯ получаю доступ к переменной-члену, которая содержит мой строковый объект, если класс, из которого я получаю Pstring, является классом, который я не написал, и я не знаю, как он реализует свои члены?

Например,

#include <string>
using namespace std;

class Pstring : public string
{
public:
  Pstring(std::string text)
   : string(text) { }

  bool isPalindrome()
  {
    // How do I access the string if I am passing it to the base class?

    // What I think I should do is...
    bool is_palindrome = true;
    auto iBegin = begin();
    auto iEnd   = end() - 1;

    while (iBegin < iEnd && is_palindrome)
    {
      if (*iBegin++ != *iEnd--)
        is_palindrome = false;
    }

    return is_palindrome;

    // But I think this is wrong because...
    // #1 The book did not discuss the keyword auto yet
    // #2 The book discussed when a class is derived from another class,
    //    how the members from super class will be accessible to the sub class.
    //    However, with this assignment, I don't see how to access the members.
  }
}

Причина, по которой я чувствую, что я делаю это неправильно, заключается в том, что в назначении упоминается с помощью индексной записи, однако я не понимаю, как использовать индексную запись, если я не знаю имя переменной, в которой находится строкахранится.

Любая помощь будет принята с благодарностью, потому что автор не предоставляет решения, если я не инструктор, которыйНа мой взгляд, он довольно отстойный.Вероятно, это связано с тем, что это академический текст.

Ответы [ 4 ]

3 голосов
/ 24 декабря 2011

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

См. Это: Наследование и переопределение функций std :: string?

Решение палиндрома (из этого вопроса: Проверьте, является ли строка палиндромом Связано с этим: C ++ Оптимизация поиска палиндрома )

#include <algorithm>

bool isPal(const string& testing) {
    return std::equal(testing.begin(), testing.begin() + testing.size() / 2, testing.rbegin());
}

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


Если вы должны использовать наследование:

class Pstring : public string
{
    //...

    bool isPalindrome()
    {
      return std::equal(begin(), begin() + size() / 2, rbegin());

      // as a side-note, 'iterator' will refer to the inherited return type of begin()
      // Also, 'operator[](x)' will call the subscript operator
    }
};
1 голос
/ 24 декабря 2011

Книга не охватывает auto, потому что это ключевое слово было добавлено в язык только недавно. Если вашему компилятору более одного года или нет, он, вероятно, не поддерживает его.

Для этой проблемы вам не нужно обращаться к каким-либо переменным-членам для правильного решения, поэтому не нужно беспокоиться о том, что они из себя представляют или достижимы ли они. Хорошая вещь, потому что ничего из этого не определено стандартом - это все детали реализации, определенные вашим конкретным компилятором, и если вы обнаружите, что копаете глубоко, вы должны спросить себя, что вы делаете неправильно.

Конечно, функции-члены родительского класса доступны в точности как функции-члены дочернего класса - вы просто вызываете их.

Перегрузки операторов-членов немного сложнее, но все же не так уж и плохо. Вам нужно предоставить экземпляр, чтобы вызвать их, *this. Вы также можете вызывать их с помощью ключевого слова operator, но, на мой взгляд, это немного неуклюже.

if ((*this)[i] == (*this)[j])

if (operator[](i) == operator[](j))
0 голосов
/ 24 декабря 2011

Попробуйте это:

#include <string>

class Pstring : public std::string
{
public:
    Pstring(const std::string &text)
        : std::string(text) { }

    bool isPalindrome()
    {
        std::string::size_type len = length();
        std::string::size_type half = len / 2;
        for (std::string::size_type idx = 0; idx < half; ++idx)
        {
            if ((*this)[idx] != (*this)[len-idx-1])
                return false;
        }
        return true;
    }
};
0 голосов
/ 24 декабря 2011

Если вы не хотите использовать авто, вместо этого вы можете просто использовать std::string::iterator, это то, что auto разрешает в любом случае в этом случае.

Таким образом, задача № 1 решена.


Когда вы звоните begin() и end(), вы звоните членам begin() и end() в суперклассе std :: string.

Таким образом, задача № 2 решена.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...