在 ostream 中使用 operator const char*

Using operator const char* in ostream

我正在尝试重载运算符 <<,以便可以使用 cout 打印错误。我需要打印 m_message 指向的 c-string。谁能帮我解决这个问题?

My Error.h header :

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 ;

}

当我执行它时,它给出了正确的输出,但它因以下错误而崩溃:

Exception thrown: read access violation.

_First 是 nullptr。

调试器:

 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));
            }

我将你的所有代码复制到一个文件中以找出问题所在。缺少 operator << () 中的测试(错误是否明确)。但是,在您的测试中,该分支不应激活。

#include <iostream>
#include <cstring>
#define _CRT_SECURE_NO_WARNINGS 

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);
} // namespace ict


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;
      return os << E.operator const char *();
    }
} // namespace ict

int main(){
  ict::Error T("Testing Error Message"); 
  std::cout << T << std::endl;
  return 0;
}

我在 Windows 10(64 位)上用 VS2013 编译了它并启动了调试器。

如您所见,我在 main() 中添加了 return 0;。实际上,可以省略它,但最好放置一个断点。因此,我得到以下输出:

Testing Error Message

嗯。那么,你描述的问题在哪里?我不喜欢这种设计(品味问题),但它按预期工作。我寻找潜在的泄漏或错误:

如果用 nullptr 调用 Error::message(),那么 strlen()(和 strcpy())可能会崩溃。如果你用 "Do not call Error::message() with a nullptr." 之类的东西记录 API 我会觉得这就足够了。

您没有提供所有信息,或者您没有在调试器中测试这个示例。

您真正需要了解的是调试器的工作原理:

  • 单击文本编辑器左侧的灰色栏可放置一个断点。在调试模式下,执行将在断点处(自动)停止。相应的源代码可见(抬起编辑器选项卡并适当滚动文本。

  • F9 ... 在当前行切换断点

  • F10 ...单步执行(单步 - 将函数作为一条语句执行)

  • F11 ...单步执行(单步-进入函数)

  • Shift F11 ... 跳出(从当前函数执行代码直到 return)

  • F5 ... 执行代码(一直到断点)

所有这些命令都可以在菜单栏和工具栏上使用。不过记住上面的键,调试起来更方便

此外,熟悉 Local, Watch, and Call Stack