2011-12-24 3 views
8

Я работаю над одной из проблем программирования в книге «Запуск с использованием C++ Early Objects 7th Edition», и одно из заданий предлагает создать класс, который является производным от строкового класса STL. Я отправляю вопрос с целью понять, что мне разрешено делать, и как я должен реализовывать решение, чтобы никто не предлагал более продвинутые предложения.Как получить доступ к переменным-членам в классе строк STL?

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

Palindrome Тестирование

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

bool isPalindrome() 

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

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

- Конец -

Моего главный вопрос, как я могу получить доступ к переменному-члену, который держит мой объект строки, если класс Я вывод 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. 
    } 
} 

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

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

+6

Никогда не проистекают из СТЛ классов. Всегда плохая идея. Почему бы вам не попробовать композицию? – Lalaland

+5

Автор не может предлагать решения, потому что он идиот. – Duck

+0

@ Ethan Steinberg Я полностью согласен, однако, это задание специально просит об этом. –

ответ

3

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

Смотреть это: Inheriting and overriding functions of a std::string?

палиндром решения (от этого вопроса: Check if a string is palindrome сшитого из этого: C++ Palindrome finder optimization)

#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 
    } 
}; 
+0

Спасибо за ответ. Я знаю, что это не очень хорошая практика. Однако задание специально просит меня реализовать мое решение так, как я пытаюсь выше. Создав класс, который получен из строкового класса STL, а затем для создания функции для проверки, является ли строка палиндром. Я пытаюсь выполнить задание. Я не могу использовать какие-либо более продвинутые методы или реализовать собственное решение, которое отличается от того, как его запрашивает задание. –

+0

@ fhaddad78 Вы можете просто перенести этот код в функцию-член. Функции участника std :: string доступны. – Pubby

+0

Спасибо за ответ. Я упустил вызов оператора [] (x) напрямую и пытался выяснить, как использовать нотацию infix. –

0

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

Таким образом, проблема № 1 выполнена.


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

Таким образом, проблема №2 выполнена.

1

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

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

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

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

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

if (operator[](i) == operator[](j)) 
+1

'auto' ключевое слово было вокруг, так как B.' auto' делает что-то полезное, это то, что было недавно добавлено. – Pubby

+0

@ Mark Ransom OK. Я собираюсь сделать это для всего плохого задания. Я был просто смущен этой проблемой, потому что в ней упоминается использование нотной записи в моем решении, которое я не понимаю, как это сделать, если я не должен перегружать оператор индекса или если моя строка не сидит в переменной-члене, которую я мог бы найти, но похоже, я не могу. –

+1

@ fhaddad78, я обновил ответ, чтобы включить операторов-членов. –

0

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

#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; 
    } 
}; 
Смежные вопросы