在ostream中使用运算符const char *

时间:2017-03-16 03:04:05

标签: c++ operator-overloading ostream

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

My Error.h标题:

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 ;

}

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

  
    

抛出异常:读取访问冲突。

  
     

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

1 个答案:

答案 0 :(得分:0)

我将所有代码复制到一个文件中以找出错误。缺少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编译它并启动调试器。

如您所见,我在return 0;中添加了main()。实际上,允许将其排除在外但是放置断点是一个好点。因此,我得到以下输出:

Testing Error Message

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

如果使用Error::message()调用nullptr,那么strlen()(和strcpy())可能会崩溃。如果您使用“请勿使用Error::message()致电nullptr”之类的方式记录API。我觉得这很充足。

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

您真正需要知道的是调试器的工作原理:

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

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

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

  • F11 ...单步执行(单步 - 输入功能)

  • 转移 F11 ...退出(执行代码直到从当前功能返回)

  • F5 ...执行代码(持续到破发点)

所有这些命令都可在菜单栏和工具栏中找到。但是,记住上述键时调试更方便。

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