课程定义:
#pragma once
#include <string>
#include <utility>
namespace impress_errors {
#define BUFSIZE 512
class Error {
public:
Error(int number);
Error(std::string message);
Error(const char *message);
bool IsSystemError();
std::string GetErrorDescription();
private:
std::pair <int, std::string> error;
char stringerror[BUFSIZE]; // Buffer for string describing error
bool syserror;
};
} // namespace impres_errors
我在文件posix_lib.cpp中有一段代码:
int pos_close(int fd)
{
int ret;
if ((ret = close(fd)) < 0) {
char err_msg[4096];
int err_code = errno;
throw impress_errors::Error::Error(err_code); //Call constructor explicitly
}
return ret;
}
在另一个文件fs_creation.cpp中:
int FSCreation::GenerateFS() {
int result;
try {
result = ImprDoMakeTree(); //This call pos_close inside.
}
catch (impress_errors::Error error) {
logger.LogERROR(error.GetErrorDescription());
return ID_FSCREATE_MAKE_TREE_ERROR;
}
catch (...) {
logger.LogERROR("Unexpected error in IMPRESSIONS MODULE");
return ID_FSCREATE_MAKE_TREE_ERROR;
}
if(result == EXIT_FAILURE) {
return ID_FSCREATE_MAKE_TREE_ERROR;
}
return ID_SUCCESS;
}
在我的编译器版本中,这个编译并正常工作:
g ++(Ubuntu / Linaro 4.4.4-14ubuntu5)4.4.5(Ubuntu Maverick - 10.04)
在另一个版本的编译器上:
g ++(Ubuntu / Linaro 4.5.2-8ubuntu4)4.5.2(Ubuntu Narwhal - 11.04)它导致
错误:
posix_lib.cpp:在函数'int pos_close(int)'中:
posix_lib.cpp:363:46:错误:无法直接调用构造函数'impress_errors :: Error :: Error'
posix_lib.cpp:363:46:错误:对于函数式转换,删除多余的':: Error'
的的问题:
1. 为什么这个工作在一个版本的g ++上,而在另一个版本的g ++上失败?
2. 当我明确地调用构造函数来创建对象时会发生什么?这是正确的吗?
为什么这有效呢?
答案 0 :(得分:5)
你没有调用构造函数(嗯,你是,但不是你的意思)。语法ClassName(constructor params)
表示使用给定的构造函数参数创建类型ClassName
的临时对象。所以你不是简单地调用构造函数;你正在创造一个对象。
所以你要创建一个Error
对象。您的问题是Error
的名称是impress_errors::Error
,而不是“impress_errors :: Error :: Error”。第二个::Error
似乎是试图命名构造函数。构造者没有名字;它们不是你能找到的功能,而是随心所欲地打电话(再次,不是你的意思)。
答案 1 :(得分:1)
这看起来像是拒绝它的编译器中的错误。代码是
合法,但不是出于你的想法。没有这样的事情
“显式调用构造函数(方法)”,因为构造函数没有
有名字(§12.1/ 1)。另一方面,impress_errors::Error::Error
是一个类型的名称; class name injection(§9/ 2)表示该类
impress_errors::Error
包含名称Error
的声明
该类,作为类之外的名称的同义词。所以
impress_errors::Error
,impress_errors::Error::Error
,
impress_errors::Error::Error::Error
等等都是同一类型
(虽然只有第一个是惯用的 - 其余的都是额外的
噪声)。当一个类型的名称后面加上括号
表达式列表,就像这里的情况一样,它是一个“明显的类型
转换(功能符号)“。(§5.2.3-并且标准说它
即使表达式列表为空,也是显式类型转换,或者
包含多个表达式 - 不要问我“类型”是什么
在这种情况下转换。)所以impress_errors::Error(err_code)
(或
impress_errors::Error::Error(err_code)
表示将err_code
转换为
impress_errors::Error
。在这种情况下,这将导致呼叫
构造函数,因为这是将int
转换为的唯一方法
impress_errors::Error
。 (然而,有可能构建案例
编译器将在其上调用用户定义的转换函数
对象被转换。)
答案 2 :(得分:0)
如果您执行编译器要求您的操作,那应该没问题。只需删除一个“错误”语句;&gt;我不确定为什么这在gcc中发生了变化,但class_name :: construction_name只是多余的。编译器知道您要调用构造函数,因为它的名称与类的名称相同
答案 3 :(得分:0)
虽然您可以使用placement new显式调用构造函数,但请参阅placement operators,但您还没有要放置对象的对象或内存块。可能更容易使用像
这样的东西抛出新的MyError(MyParams);
并使异常处理程序负责删除它。 FWIW Microsoft将此方法与MFC一起使用。
答案 4 :(得分:0)
我遇到了完全相同的错误消息。
解决方案是改变这一行:
throw impress_errors::Error::Error(err_code); //Call constructor explicitly
到
throw impress_errors::Error(err_code); //Call constructor explicitly
在C ++中,您可以在派生类构造函数中调用基类构造函数,只是从不使用范围解析运算符::