2011-12-24 13 views
8

Estoy trabajando en uno de los desafíos de programación en el libro Starting Out With C++ Early Objects 7ma edición y una de las asignaciones pide crear una clase que se deriva de la clase de cadena STL. Estoy publicando la pregunta con el fin de comprender lo que se me permite hacer y cómo se supone que debo implementar la solución para que nadie ofrezca sugerencias más avanzadas.¿Cómo accedo a las variables miembro en la clase de cadena STL?

- pregunta como está escrito en el texto -

palíndromo Prueba

un palíndromo es una cadena que se lee igual hacia atrás como hacia adelante. Por ejemplo, las palabras mamá, papá, señora y radar son palíndromos. Escriba un class Pstring derivado del STL string class. El Pstring class añade una función miembro

bool isPalindrome() 

que determina si la cadena es un palíndromo. Incluya un constructor que tome un objeto STL string como parámetro y lo pase al constructor de la clase base de cadena. Pruebe su clase teniendo un programa principal que le pida al usuario que ingrese una cadena. El programa usa la cadena para inicializar un objeto Pstring y luego llama a isPalindrome() para determinar si la cadena ingresada es un palíndromo.

Puede ser útil utilizar el operador de subíndice [] de la clase de cadena: si str es un objeto de cadena yk es un entero, entonces str [k] devuelve el caracter en la posición k en la cadena.

- Fin -

Mi pregunta principal es ¿cómo puedo acceder a la variable miembro que ejerza mi objeto de cadena si la clase estoy derivando PString de una clase que no he escrito y no sé cómo implementa sus miembros?

Por ejemplo,

#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 razón por la que siento que estoy haciendo esto de forma incorrecta se debe a la asignación menciona usando la notación de subíndice, sin embargo, no entiendo cómo utilizar la notación de subíndice si yo no' t saber el nombre de la variable donde se almacena la cadena.

Cualquier ayuda sería muy apreciada porque el autor no proporciona las soluciones a menos que yo sea un instructor que es bastante cojo en mi opinión. Probablemente tiene que ver con el hecho de que este es un texto académico.

+6

Nunca se derivan de las clases STL. Siempre una mala idea. ¿Por qué no pruebas la composición? – Lalaland

+5

El autor puede no proporcionar soluciones porque es un idiota. – Duck

+0

@Ethan Steinberg Estoy completamente de acuerdo, sin embargo, esta tarea específicamente pide que haga eso. –

Respuesta

3

No debe heredar de std :: string, ya que no fue diseñado para eso, ni lo necesita para encontrar un palindrome.

ver esto: Inheriting and overriding functions of a std::string?

solución palíndromo (a partir de esta pregunta: Check if a string is palindrome enlaces desde ésta: C++ Palindrome finder optimization)

#include <algorithm> 

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

de calidad de ese libro parece cuestionable. Las funciones gratuitas (dependiendo de a quién se las pregunte) casi siempre son preferibles a las funciones de los miembros, y especialmente preferidas a las de herencia.


Si debe utilizar la herencia:

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

Gracias por la respuesta. Soy consciente de que esta no es una buena práctica. Sin embargo, la tarea específicamente me pide que implemente mi solución de la forma en que intento hacerlo anteriormente. Creando una clase que se deriva de la clase de cadena STL y luego crea una función para probar si una cadena es un palíndromo. Estoy tratando de completar la tarea. No puedo usar ningún método más avanzado ni implementar mi propia solución, que se aparta de la forma en que la tarea lo solicita. –

+0

@ fhaddad78 Puede simplemente ajustar ese código en una función miembro. Las funciones de miembro de std :: string todavía están disponibles. – Pubby

+0

Gracias por la respuesta. Pasé por alto llamar al operador [] (x) directamente y estaba tratando de descubrir cómo usar la notación infija. –

0

Si no desea utilizar auto, a continuación, puede simplemente usar std::string::iterator su lugar, que es lo que auto es resolver de todos modos en este caso.

Por lo tanto, el problema # 1 está satisfecho.


Cuando usted está llamando begin() y end() que está llamando a los miembros begin() y end() en la superclase std :: string.

Por lo tanto, el problema # 2 está satisfecho.

1

El libro no cubrió auto porque esa palabra clave se agregó recientemente al idioma. Si tu compilador tiene más de un año o no es uno de los grandes nombres, probablemente no lo admita.

Para este problema no necesita acceder a ninguna variable miembro para obtener una solución adecuada, por lo que no hay necesidad de preocuparse por lo que son o si son alcanzables. Lo bueno, porque nada de eso está especificado por el estándar, son todos los detalles de implementación definidos por tu compilador particular, y si te das cuenta de que estás cavando profundamente, debes preguntarte qué estás haciendo mal.

Por supuesto, se accede a las funciones miembro de la clase principal exactamente como las funciones miembro de la clase secundaria; usted simplemente las llama.

Las sobrecargas del operador miembro son un poco más complicadas, pero aún así no están tan mal. Debe proporcionar la instancia para invocarlos, que es *this. También puede llamarlos con la palabra clave operator, pero en mi opinión eso es un poco más torpe.

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

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

'auto' la palabra clave ha existido desde B.' auto' haciendo algo útil es lo que se agregó recientemente. – Pubby

+0

@Mark Ransom OK. Voy a atribuir esto solo a una mala tarea, todos juntos. Estaba realmente confundido por este problema porque menciona el uso de notación de subíndice en mi solución que no entiendo cómo hacerlo a menos que tuviera que sobrecargar el operador de subíndice o a menos que mi cadena estuviera en una variable miembro que pudiera localizar, pero parece que no puedo –

+1

@ fhaddad78, actualicé la respuesta para incluir operadores miembros. –

0

Prueba esto:

#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; 
    } 
}; 
Cuestiones relacionadas