2011-12-24 20 views
8

Sto lavorando a una delle sfide di programmazione nel libro Starting Out With C++ Early Objects 7th Edition e uno dei compiti richiede di creare una classe derivata dalla classe di stringhe STL. Sto postando la domanda allo scopo di capire cosa sono autorizzato a fare e come dovrei implementare la soluzione in modo che nessuno offra suggerimenti più avanzati.Come accedere alle variabili membro nella classe di stringa STL?

- Domanda come è scritto nel testo -

Palindrome Testing

un palindromo è una stringa che legge lo stesso all'indietro come in avanti. Ad esempio, le parole mamma, padre, signora e radar sono palindromi. Scrivi un class Pstring derivato dallo STL string class. Il Pstring class aggiunge una funzione membro

bool isPalindrome() 

che determina se la stringa è palindroma. Includere un costruttore che prende un oggetto STL string come parametro e lo passa al costruttore della classe base della stringa. Metti alla prova la tua classe con un programma principale che chiede all'utente di inserire una stringa. Il programma utilizza la stringa per inizializzare un oggetto Pstring e quindi chiama isPalindrome() per determinare se la stringa immessa è un palindromo.

Potrebbe essere utile utilizzare l'operatore pedice [] della classe string: se str è un oggetto stringa e k è un numero intero, quindi str [k] restituisce il carattere nella posizione k nella stringa.

- Fine -

La mia domanda principale è come faccio ad accedere alla variabile membro che detiene il mio oggetto stringa se la classe che sto derivante da Pstring è una classe che non ho scritto e io non so come implementa i suoi membri?

Per esempio,

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

La ragione per cui mi sento come sto facendo questo è errato perché l'assegnazione menziona usando la notazione pedice, tuttavia, non capisco come usare la notazione pedice se I don' so il nome della variabile in cui è memorizzata la stringa.

Qualsiasi aiuto sarebbe molto apprezzato perché l'autore non fornisce le soluzioni a meno che non sia un istruttore che è piuttosto zoppo secondo me. Probabilmente ha a che fare con il fatto che questo è un testo accademico.

+6

Mai derivano dalle classi STL. Sempre una cattiva idea Perché non provi invece la composizione? – Lalaland

+5

L'autore non può fornire soluzioni perché è un idiota. – Duck

+0

@Ethan Steinberg Sono completamente d'accordo, tuttavia, questo incarico richiede specificamente di farlo. –

risposta

3

Non si dovrebbe ereditare da std :: string, poiché non è stato progettato per questo, né è necessario per trovare un palindrome.

vedere questo: Inheriting and overriding functions of a std::string?

soluzione Palindrome (da questa domanda: Check if a string is palindrome collegati a questa: C++ Palindrome finder optimization)

#include <algorithm> 

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

qualità che del libro sembra discutibile. Le funzioni libere (a seconda di chi le chiedi) sono quasi sempre preferite rispetto alle funzioni dei membri, e specialmente preferite rispetto all'ereditarietà.


Se è necessario utilizzare l'ereditarietà:

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

Grazie per la risposta. Sono consapevole che questa non è una buona pratica. Tuttavia, il compito in particolare mi chiede di implementare la mia soluzione nel modo in cui sto tentando di sopra. Creando una classe derivata dalla classe di stringa STL e quindi creando una funzione per verificare se una stringa è un palindromo. Sto cercando di completare il compito. Non posso usare metodi più avanzati o implementare la mia soluzione che si discosti da come l'incarico lo richiede. –

+0

@ fhaddad78 Puoi semplicemente avvolgere quel codice in una funzione membro. Le funzioni membro std :: string sono ancora disponibili. – Pubby

+0

Grazie per la risposta. Ho trascurato direttamente l'operatore chiamante [] (x) e stavo cercando di capire come usare la notazione infissa. –

0

Se non si desidera utilizzare auto, allora si può semplicemente utilizzare std::string::iterator invece, che è quello che auto sta risolvendo a ogni modo in questo caso.

Quindi il problema n. 1 è soddisfatto.


Quando si sta chiamando begin() e end() che si sta chiamando i membri begin() e end() nella superclasse std :: string.

Quindi il problema n. 2 è soddisfatto.

1

Il libro non copre auto perché quella parola chiave è stata aggiunta solo di recente alla lingua. Se il tuo compilatore ha più di un anno o non è uno dei grandi nomi, probabilmente non lo supporta.

Per questo problema non è necessario accedere a qualsiasi variabile membro per una soluzione adeguata, quindi non è necessario preoccuparsi di ciò che sono o se sono raggiungibili. La cosa buona, perché nessuno di questi è specificato dallo standard - sono tutti i dettagli di implementazione definiti dal tuo particolare compilatore, e se ti ritrovi a scavare così profondamente dovresti chiederti cosa stai facendo male.

Ovviamente le funzioni membro della classe genitore sono accessibili esattamente come funzioni membro della classe figlio - basta chiamarle.

I sovraccarichi degli operatori membri sono un po 'più complicati, ma non troppo male. È necessario fornire l'istanza per invocarli contro, che è *this. Puoi anche chiamarli con la parola chiave operator ma a mio avviso è un po 'più scomodo.

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

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

'auto' la parola chiave è presente da B.' auto' facendo qualcosa di utile è ciò che è stato aggiunto di recente. – Pubby

+0

@Mark Ransom OK. Sto andando in gesso solo per un cattivo incarico tutti insieme. Ero solo molto confuso da questo problema perché menzionava l'uso della notazione di pedice nella mia soluzione che non capisco come fare a meno che non sovraccarico l'operatore di pedice o a meno che la mia stringa fosse seduta in una variabile membro che potrei localizzare, ma sembra che non possa. –

+1

@ fhaddad78, ho aggiornato la risposta per includere gli operatori membri. –

0

Prova questo:

#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; 
    } 
}; 
Problemi correlati