我们知道std::exception
和 java.lang.Exception
分别是C++和Java语言的大部分异常类型的基类。如果我们要定义一个自己的异常类型,一般会以这两个类做基类来写自己的类代码。这是我在写C++和Java代码的时的理解,觉得这俩货是一样的。
最近在研究Java到C++代码自动转换时(将项目中的一部分java代码自动翻译成C++代码),才发现在细节上这两个类还是有区别的。
下面是java中java.lang.Exception类的定义,
可以看到除了默认构造函数之外,还有另外三个构造函数。再看std::exception,在C++标准定义中除了默认构造函数外,只有一个构造函数。
http://www.cplusplus.com/reference/exception/exception/exception/
而实际gcc中对std::exception的定义就只有默认构造函数了(参见后面gcc的std::exception代码)
区别,这就是区别,所以在C++下 std::exception("hello")
这样的写法是不对的,因为没有对应的构造函数。所以原本Java代码中throw new Exception("hello");
这样的语句,就不能直接翻译成throw new std::exception("hello");
既然std::exception
不能用来替代Java的java.lang.Exception
,那么替代方案就是std::logic_error
来替代java.lang.Exception
虽然不清楚为什么std::exception要做这样的定义,算不算个bug,但是使用起来确实很不方便啊。
大概microsoft发现了这个问题实在忍不了了,所以msvc中的std::exception
就在标准C++基础上做了扩充,增加了exception(char const* const _Message)
和exception(exception const& _Other)
构造函数(参见后面的代码)。
java中java.lang.Exception类代码
/*
* %W% %E%
*
* Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package java.lang;
/**
* The class <code>Exception</code> and its subclasses are a form of
* <code>Throwable</code> that indicates conditions that a reasonable
* application might want to catch.
*
* @author Frank Yellin
* @version %I%, %G%
* @see java.lang.Error
* @since JDK1.0
*/
public class Exception extends Throwable {
static final long serialVersionUID = -3387516993124229948L;
/**
* Constructs a new exception with <code>null</code> as its detail message.
* The cause is not initialized, and may subsequently be initialized by a
* call to {@link #initCause}.
*/
public Exception() {
super();
}
/**
* Constructs a new exception with the specified detail message. The
* cause is not initialized, and may subsequently be initialized by
* a call to {@link #initCause}.
*
* @param message the detail message. The detail message is saved for
* later retrieval by the {@link #getMessage()} method.
*/
public Exception(String message) {
super(message);
}
/**
* Constructs a new exception with the specified detail message and
* cause. <p>Note that the detail message associated with
* <code>cause</code> is <i>not</i> automatically incorporated in
* this exception's detail message.
*
* @param message the detail message (which is saved for later retrieval
* by the {@link #getMessage()} method).
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A <tt>null</tt> value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public Exception(String message, Throwable cause) {
super(message, cause);
}
/**
* Constructs a new exception with the specified cause and a detail
* message of <tt>(cause==null ? null : cause.toString())</tt> (which
* typically contains the class and detail message of <tt>cause</tt>).
* This constructor is useful for exceptions that are little more than
* wrappers for other throwables (for example, {@link
* java.security.PrivilegedActionException}).
*
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A <tt>null</tt> value is
* permitted, and indicates that the cause is nonexistent or
* unknown.)
* @since 1.4
*/
public Exception(Throwable cause) {
super(cause);
}
}
gcc中std::exception的代码
/**
* @brief Base class for all library exceptions.
*
* This is the base class for all exceptions thrown by the standard
* library, and by certain language expressions. You are free to derive
* your own %exception classes, or use a different hierarchy, or to
* throw non-class data (e.g., fundamental types).
*/
class exception
{
public:
exception() _GLIBCXX_USE_NOEXCEPT { }
virtual ~exception() _GLIBCXX_USE_NOEXCEPT;
/** Returns a C-style character string describing the general cause
* of the current error. */
virtual const char* what() const _GLIBCXX_USE_NOEXCEPT;
};
msvc中std::exception的代码
class exception
{
public:
exception() throw()
: _Data()
{
}
explicit exception(char const* const _Message) throw()
: _Data()
{
__std_exception_data _InitData = { _Message, true };
__std_exception_copy(&_InitData, &_Data);
}
exception(char const* const _Message, int) throw()
: _Data()
{
_Data._What = _Message;
}
exception(exception const& _Other) throw()
: _Data()
{
__std_exception_copy(&_Other._Data, &_Data);
}
exception& operator=(exception const& _Other) throw()
{
if (this == &_Other)
{
return *this;
}
__std_exception_destroy(&_Data);
__std_exception_copy(&_Other._Data, &_Data);
return *this;
}
virtual ~exception() throw()
{
__std_exception_destroy(&_Data);
}
virtual char const* what() const
{
return _Data._What ? _Data._What : "Unknown exception";
}
private:
__std_exception_data _Data;
};