2017-03-16 2 views
0

J'essaye de surcharger l'opérateur << afin que l'erreur puisse être imprimée en utilisant cout. Je dois imprimer le c-string pointé par m_messag e. Quelqu'un peut-il m'aider à résoudre ce problème?Utilisation de l'opérateur const char * dans ostream

My Error.h tête:

ifndef ICT_ERROR_H_ 
#define ICT_ERROR_H_ 

#include <iostream> 
namespace ict { 
    class Error { 
     char* m_message; 
    public: 
    // constructors 
     Error(); 
     Error(const char* errorMessage); 
    // destructor 
     virtual ~Error(); 
    // deleted constructor and operator= 
     Error(const Error& em) = delete; 
     Error& operator=(const Error& em) = delete; 
    // operator= for c-style strings 
     void operator=(const char* errorMessage); 
    // methods 
     void clear(); 
     bool isClear()const; 
     void message(const char* value); 
    // cast overloads 
     operator const char*() const; 
     operator bool()const; 
    }; 
    // operator << overload prototype for cout 
    std::ostream& operator<<(std::ostream& os, const Error& E); 
} 
#endif 

Error.cpp 

#define _CRT_SECURE_NO_WARNINGS 
#include <cstring> 
#include "Error.h" 

namespace ict{ 
    Error::Error() 
    { 
     m_message = nullptr; 
    } 
    Error::Error(const char * errorMessage) 
    { 
     m_message = nullptr; 
     message(errorMessage); 

    } 
    Error::~Error() 
    { 
     delete[] m_message; 
    } 
    void Error::operator=(const char * errorMessage) 
    { 
     clear(); 
     message(errorMessage); 
    } 
    void Error::clear() 
    { 
     delete[] m_message; 
     m_message = nullptr; 
    } 
    bool Error::isClear() const 
    { 
     bool status = false; 
     if (m_message==nullptr) { 
      status = true; 
     } 
     return status; 
    } 
    void Error::message(const char * value) 
    { 
     delete[] m_message; 
     m_message = new char[strlen(value)+1]; 
     strcpy(m_message,value); 
    } 
    Error::operator const char*() const 
    { 

     return m_message; 
    } 
    Error::operator bool() const 
    { 
     return isClear(); 
    } 
    ***std::ostream& operator<<(std::ostream& os, const Error& E) { 
     if (E.isClear()) { 

     } 
     return os << E.operator const char *(); 

    }*** 
} 

Main.cpp 

int main(){ 
    Error T("Testing Error Message"); 
    cout << T << endl ; 

} 

Quand je l'exécute, il donne la sortie correcte, mais il se bloque avec l'erreur suivante:

Exception lancée: lire violation d'accès.

_First était nullptr.

Debugger:

static size_t __CLRCALL_OR_CDECL length(const _Elem *_First) 
      { // find length of null-terminated string 
    //next statement to be executed ---> return (*_First == 0 ? 0 
       : _CSTD strlen(_First)); 
      } 
+0

Et lorsque vous avez parcouru votre code à l'aide d'un débogueur, sur quelle ligne votre débogueur a-t-il prétendu que l'exception s'est produite? –

+0

@SamVarshavchik Je suis désolé, je ne suis pas très familier avec le débogueur Visual C++, mais il semble me pointer vers le code du débogueur ci-dessus au lieu d'une ligne spécifique dans mon fichier Error.cpp – elvisi27

+0

@SamVarshavchik je pense que le problème est sur la ligne 57 : retourne l'os << E.operator const char *() quand il est imprimé sur la ligne 17 sur main.cpp: cout << T << endl; – elvisi27

Répondre

0

Je copié tout votre code dans un fichier pour savoir ce qui ne va pas. Le test dans operator <<() (si l'erreur est claire) était manquant. Toutefois, dans votre test, cette branche ne doit pas devenir active. Je l'ai compilé avec VS2013 sous Windows 10 (64 bits) et j'ai lancé le débogueur.

Comme vous le voyez j'ai ajouté return 0; dans main(). En fait, il est permis de le laisser de côté mais c'est un bon point pour placer un point d'arrêt. Ainsi, j'ai obtenu la sortie suivante:

Testing Error Message 

Hmm. Alors, où est le problème que vous avez décrit? Je n'aime pas le design (une question de goût) mais ça fonctionne comme prévu. Je cherchais des fuites potentielles ou des bugs:

Si Error::message() est appelée avec un nullptr puis strlen() (et strcpy()) plantera probablement. Si vous documentez l'API avec quelque chose comme "Ne pas appeler Error::message() avec un nullptr." Je trouverais cela suffisant.

Soit vous n'avez pas fourni toutes les informations, soit vous n'avez pas testé cet exemple dans votre débogueur.

Ce que vous avez vraiment besoin de savoir est comment votre débogueur fonctionne:

  • cliquant dessus dans la barre grise gauche de l'éditeur de texte (s) met un point de rupture. En mode débogage, l'exécution s'arrêtera (automatiquement) aux points de rupture. Le code source correspondant est rendu visible (soulevant l'onglet éditeur et en faisant défiler le texte de manière appropriée.

  • F9 ... point de rupture bascule dans la ligne actuelle

  • F10 ... enjamber (simple step - exécute les fonctions en une seule instruction)

  • F11 ...étape dans (seule étape - la saisie de fonctions)

  • MajF11 ... sortir (exécuter du code jusqu'à ce que le retour de la fonction actuelle)

  • F5 ... exécuter du code (en continu jusqu'à point de rupture)

Toutes ces commandes sont disponibles dans la barre de menus et dans la barre d'outils. Cependant, le débogage est plus pratique en se souvenant des clés ci-dessus. En outre, familiarisez-vous avec Local, Watch, and Call Stack.

+0

Il semble que tout ce dont il avait besoin pour travailler était juste d'ajouter "return os;" après if (E.isclear()). Merci beaucoup pour votre aide avec le débogueur aussi. – elvisi27