Я извлек пользовательский класс исключений из std::runtime_error
Статический анализатор выдает мне предупреждение о том, что если я определю или удалим операцию по умолчанию (операторы копирования, операторы копирования / перемещения, деструкторы и т. Д.), ЯЯ должен определить или удалить их все.
, чтобы устранить это глупое предупреждение, я написал пропущенный оператор присваивания, но потом получил другое предупреждение, что теперь мой оператор скрывает базовый не виртуальный оператор присваивания!
Так какВ базовом классе есть закрытые члены, которые я не могу скопировать. Похоже, единственное решение состоит в том, чтобы вызвать базовый оператор присваивания непосредственно для части базового объекта, а затем скопировать оставшуюся часть *this
объекта и, наконец, вернуть *this
, но до этогоделая это, я взглянул на то, что делает база operator=
, и вот как это выглядит:
exception& operator=(exception const& _Other) noexcept
{
if (this == &_Other)
{
return *this;
}
__std_exception_destroy(&_Data);
__std_exception_copy(&_Other._Data, &_Data);
return *this;
}
private:
__std_exception_data _Data;
};
Теперь, зная, что вот моя реализация (с комментариями) для вызова назначения базы и копирования остальныхпроизводного объекта:
class Exception :
public std::runtime_error
{
public:
// ...
Exception& operator=(const Exception& other)
{
if (this == &other)
{
return *this;
}
// first copy only base class data to *this
*dynamic_cast<std::runtime_error*>(this) =
runtime_error::operator=(
*dynamic_cast<std::runtime_error*>(
const_cast<Exception*>(&other)));
// then copy derived class data to *this
mInfo = other.mInfo;
mCode = other.mCode;
// finally return complete copy
return *this;
}
private:
std::error_code mCode;
std::string mInfo;
};
Это правильный способ сделать это? Я думаю, что это похоже на проблему, но я не уверен.
РЕДАКТИРОВАТЬ
вот полный класс, для справки:
#pragma warning (disable : 4275) // base needs to have DLL interface
class ERROR_API Exception :
public std::runtime_error
{
public:
~Exception() noexcept; // cant be inlined in release build
// default/delete
Exception(const Exception&) = default;
Exception(Exception&&) = delete;
Exception& operator=(const Exception& other)
{
if (this == &other)
{
return *this;
}
// copy base class data to *this
*dynamic_cast<std::runtime_error*>(this) =
runtime_error::operator=(
*dynamic_cast<std::runtime_error*>(
const_cast<Exception*>(&other)));
// copy derived class data to *this
mInfo = other.mInfo;
mCode = other.mCode;
return *this;
}
Exception& operator=(Exception&&) = delete;
/** Construct from error enum */
template<typename Enum>
Exception(Enum err_enum);
/** Construct from error enum and string*/
template<typename Enum>
Exception(Enum err_enum, String message);
/** Construct from error_code object */
inline Exception(std::error_code err_code);
/** Construct from error_code object and string */
inline Exception(std::error_code err_code, String message);
/** Get error_condidtion name */
inline virtual std::string ConditionName() const;
/** Get error_category name */
inline virtual std::string CategoryName() const;
/** Get error_condition value */
inline virtual int ConditionValue() const noexcept;
/** Get error_condition value */
inline virtual int ErrorValue() const noexcept;
/** Get additional information string passed to constructor */
inline virtual const String& GetInfo() const noexcept;
/** Get error_code object associated with this exception object */
inline virtual const std::error_code& code() const noexcept;
private:
SUPPRESS(4251); // member needs to have DLL interface
std::error_code mCode;
SUPPRESS(4251); // member needs to have DLL interface
String mInfo;
};
#pragma warning (default : 4275) // base needs to have DLL interface