2011-12-24 11 views
8

Pracuję nad jednym z wyzwań programowania w książce Początek z C++ Early Objects 7th Edition, a jedno z zadań prosi o utworzenie klasy, która wywodzi się z klasy ciągów STL. Publikuję pytanie w celu zrozumienia, co mogę zrobić i jak mam wdrożyć to rozwiązanie, aby nikt nie oferował bardziej zaawansowanych sugestii.Jak uzyskać dostęp do zmiennych członkowskich w klasie ciągów STL?

- Pytanie, jak to jest napisane w tekście -

Palindrome Testowanie

palindrom to ciąg znaków, który brzmi tak samo jak do przodu do tyłu. Na przykład słowa mama, tata, madam, i radar są palindromami. Napisz class Pstring, który pochodzi z STL string class. Pstring class dodaje funkcję składową

bool isPalindrome() 

która określa, czy ciąg jest palindrom. Dołącz konstruktor, który pobiera obiekt STL string i przekazuje go do konstruktora klasy łańcuchowej. Sprawdź swoją klasę, uruchamiając program główny, który prosi użytkownika o wprowadzenie ciągu znaków. Program używa łańcucha do zainicjowania obiektu Pstring, a następnie wywołuje funkcjęPalindrome() w celu ustalenia, czy wprowadzony łańcuch jest palindromem.

Może się okazać, że użyteczne jest użycie operatora [] [] klasy ciągów: jeśli str jest obiektem typu string, a k jest liczbą całkowitą, to str [k] zwraca znak char w pozycji k w ciągu znaków.

- Koniec -

Moje główne pytanie brzmi: jak mogę uzyskać dostęp do zmiennej członka, który posiada mój obiekt string jeśli klasa ja wynikające z Pstring to klasa nie pisałem i nie wiem jak wdraża swoich członków?

Na przykład

#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. 
    } 
} 

Powodem czuję, że robię to dlatego, że nieprawidłowo przypisanie wspomina notacji indeksu, jednak nie rozumiem jak używać notacji indeksie jeśli don” t znać nazwę zmiennej, w której zapisany jest ciąg znaków.

Każda pomoc byłaby bardzo doceniana, ponieważ autor nie zapewnia rozwiązań, chyba że jestem instruktorem, który jest moim zdaniem kiepski. Prawdopodobnie ma to związek z faktem, że jest to tekst akademicki.

+6

Nigdy nie wywodzą się z klas STL. Zawsze zły pomysł. Dlaczego zamiast tego nie chcesz wypróbować kompozycji? – Lalaland

+5

Autor może nie dostarczyć rozwiązań, ponieważ jest idiotą. – Duck

+0

@Ethan Steinberg Całkowicie się zgadzam, jednak zadanie to konkretnie wymaga tego. –

Odpowiedz

3

Nie powinieneś dziedziczyć ze std :: string, ponieważ nie został on zaprojektowany do tego celu, ani nie musisz szukać palindromu.

Zobacz to: Inheriting and overriding functions of a std::string?

rozwiązanie palindrom (od tego pytania: Check if a string is palindrome połączonej z tego: C++ Palindrome finder optimization)

#include <algorithm> 

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

jakość tej książki wydaje się wątpliwa. Darmowe funkcje (w zależności od tego, kogo pytasz) są prawie zawsze preferowane w stosunku do funkcji członkowskich, a szczególnie preferowane w stosunku do dziedziczenia.


Jeśli trzeba użyć dziedziczenia:

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

Dziękuję za odpowiedź. Wiem, że to nie jest dobra praktyka. Jednak zadanie konkretnie prosi mnie o wdrożenie mojego rozwiązania w taki sposób, w jaki próbuję to zrobić powyżej. Tworząc klasę, która pochodzi z klasy ciągów STL, a następnie tworzy funkcję do testowania, czy łańcuch jest palindromem. Próbuję wykonać zadanie. Nie mogę używać bardziej zaawansowanych metod ani wdrażać własnych rozwiązań, które odbiegają od tego, w jaki sposób zadanie to zleca. –

+0

@ fhaddad78 Możesz po prostu zawinąć ten kod w funkcji składowej. Funkcje członkowskie std :: string są nadal dostępne. – Pubby

+0

Dzięki za odpowiedź. Nie zwracałem uwagi na wywoływanie operatora [] (x) bezpośrednio i próbowałem dowiedzieć się, jak korzystać z zapisu infiksów. –

0

Jeśli nie chcesz używać auto, to możesz po prostu użyć std::string::iterator zamiast, co jest, co auto jest rozwiązanie do tak czy inaczej w tym przypadku.

Tak więc problem nr 1 jest spełniony.


Kiedy dzwonisz begin() i end() dzwonisz członków begin() i end() w nadklasy std :: string.

Tak więc problem nr 2 jest spełniony.

1

Książka nie obejmuje auto, ponieważ to słowo kluczowe zostało niedawno dodane do tego języka. Jeśli twój kompilator ma ponad rok lub nie jest jednym z wielkich nazw, prawdopodobnie go nie obsługuje.

Aby rozwiązać ten problem, nie trzeba uzyskiwać dostępu do zmiennych członkowskich w celu znalezienia właściwego rozwiązania, więc nie trzeba się martwić o to, jakie one są i czy są dostępne. Dobrze, ponieważ żadna z nich nie jest określona przez standard - to wszystkie szczegóły implementacji zdefiniowane przez twój konkretny kompilator, a jeśli głęboko w to wkopiesz, powinieneś zadać sobie pytanie, co robisz źle.

Oczywiście funkcje członkowskie klasy nadrzędnej są dostępne dokładnie jako funkcje członkowskie klasy dziecka - po prostu je wywołujesz.

Przeciążenie operatora użytkownika jest nieco trudniejsze, ale nadal nie jest takie złe. Musisz podać instancję, aby je wywołać, czyli *this. Możesz również wywoływać je słowami kluczowymi operator, ale moim zdaniem jest to trochę niezdarne.

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

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

'auto' słowo kluczowe było w pobliżu, ponieważ' auto' robi coś użytecznego, co zostało ostatnio dodane. – Pubby

+0

@ Mark Ransom OK. Zamierzam to wszystko spisać do złego zadania. Byłem po prostu bardzo zdezorientowany tym problemem, ponieważ wspomina on o używaniu w moim rozwiązaniu notacji dolnego źródła, której nie rozumiem, jak to zrobić, chyba że przeładowałem operatora indeksu dolnego lub jeśli mój ciąg byłby w zmiennej członkowskiej, którą mógłbym zlokalizować, ale wydaje się, że nie mogę. –

+1

@ fhaddad78, zaktualizowałem odpowiedź, aby uwzględnić operatorów członkowskich. –

0

Spróbuj tego:

#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; 
    } 
}; 
Powiązane problemy