通过调用构造函数(方法)类的明确
定义构造对象:通过调用构造函数(方法)类的明确
#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;
}
在我的编译器的版本与一个被编译和工作正确:
克++(Ubuntu的/ Linaro的4.4.4-14ubuntu5)4.4.5(Ubuntu的小牛 - 10.04)
在编译器的另一个版本:
克++(Ubuntu的/ Linaro的4.5.2-8ubuntu4)4.5.2(Ubuntu的独角鲸 - 11.04)它会导致
错误:
posix_lib.cpp:在函数 '诠释pos_close(INT)':
posix_lib.cpp:363:46:错误:无法直接调用构造函数'impress_errors :: Error :: Error'
posix_lib.cpp:363:46:错误:对于函数样式转换,删除多余的':: Error'
问题:
1. 为什么这个工作在一个版本的g ++,并在另一个版本上失败?
2. 当我显式调用创建对象的构造函数时会发生什么?这是对的吗?
为什么这是行得通的?
它应该可以,如果你做什么编译器问你。只要删除一个“错误”语句;>我不知道为什么这改变了gcc,但class_name :: construction_name只是多余的。编译器知道你想调用构造函数,因为它的名字与类的名字相同
你没有调用构造函数(当然,你是,但不是你的意思)。语法ClassName(constructor params)
表示使用给定参数作为其构造函数,创建ClassName
类型的临时对象。所以你不是简单地调用构造函数;你正在创建一个对象。
因此您正在创建一个Error
对象。你的问题是,Error
的名称是impress_errors::Error
,而不是“impress_errors :: Error :: Error”。第二个::Error
似乎是一个尝试命名构造函数。构造函数没有名字;他们不是你可以随心所欲地找到和调用的功能(再次,不是你的意思)。
这看起来像编译器中的一个错误,拒绝它。代码为 合法,但不是您认为的理由。 “ ”没有明确地调用构造函数(方法)“,因为构造函数不包含名称(§12.1/ 1)的 。另一方面,impress_errors::Error::Error
是一个类型的名称;类名注入(§9/ 2)意味着类 impress_errors::Error
包含名称为Error
的声明 该类,作为该类名外的同义词。所以 impress_errors::Error
,impress_errors::Error::Error
, impress_errors::Error::Error::Error
等所有名称都是同一类型 (尽管只有第一个是惯用的—其余的都是只有额外的 噪音)。当类型的名称后跟加括号的 表达式列表时,就像这里的情况一样,它是一个“Explicity type conversion(功能符号)”。 (第5.2.3节—和标准说它是 即使表达式列表是空的,或者 包含多个表达式—也不问我在这种情况下转换的“类型”是 。 )所以impress_errors::Error(err_code)
(或 impress_errors::Error::Error(err_code)
手段转换err_code
成 的impress_errors::Error
。其中,在这种情况下,将导致调用 构造,因为这是一个int
转换成 impress_errors::Error
的唯一途径。(这是可能的,然而,构造个案 ,其中编译器将调用 对象上的用户定义的转换函数)
尽管您可以使用placement new显式调用构造函数,请参见placement operators,但您没有用于放置对象的对象或内存块。可能更容易使用像
扔新MyError(MyParams);
并使异常处理程序负责删除它。 FWIW微软在MFC中使用这种方法。
通常new''new异常对象是个坏主意,希望处理程序删除它;更好地直接抛出对象并避免内存泄漏的可能性。 –
我遇到了完全相同的错误消息。
解决的办法是改变这一行:
throw impress_errors::Error::Error(err_code); //Call constructor explicitly
到
throw impress_errors::Error(err_code); //Call constructor explicitly
在C++中,你可以调用派生类构造函数中的基类的构造函数,只是从来没有使用范围解析操作: :
@James Kanze:§3.4.3.1/ 2似乎另有说明。我在这里没有最终的标准,只有n3290,但我确信最终文件在这个部门没有太大变化。这似乎意味着'impress_errors :: Error :: Error'不能用作类型名称,尽管注入。 –
@n.m我正在看n3291,但我不明白它在这里如何应用。 §3.4.3.1/ 2首先说“在构造函数是一个 可接受的查找结果[...]”的查找中,在这里不是这种情况。 –
那里的例子说'A :: A a; //错误,A :: A不是类型名称,为什么?它可以是另一个位置的类型名称吗?我知道例子不是规范的,但是这里的意图是什么? –