C++ 通过显式调用构造函数(方法)构造对象
类的定义:C++ 通过显式调用构造函数(方法)构造对象,c++,object,constructor,C++,Object,Constructor,类的定义: #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(
#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
在我的编译器版本中,此版本已编译且工作正常:g++(Ubuntu/Linaro4.4.4-14ubuntu5)4.4.5(Ubuntu Maverick-10.04)
另一版本的编译器:
g++(Ubuntu/Linaro 4.5.2-8ubuntu4)4.5.2(Ubuntu独角鲸-11.04)它导致了
错误:
posix_lib.cpp:在函数“int pos_close(int)”中:
posix_lib.cpp:363:46:错误:无法直接调用构造函数'impress_errors::error::error'
posix_lib.cpp:363:46:错误:对于函数样式转换,删除冗余的“::错误”
问题:
1.为什么这在一个版本的g++上工作,而在另一个版本上失败了?
2.当我显式调用构造函数来创建对象时会发生什么?是否正确?
为什么会这样呢?如果按照编译器的要求去做,应该没问题。只需删除一条“错误”语句;>我不知道为什么在gcc中会发生这种变化,但class_name::construction_name只是多余的。编译器知道您想要调用构造函数,因为它的名称与类的名称相同,您没有调用构造函数(当然,您是这样,但不是按照您的意思)。语法
ClassName(构造函数参数)
意味着使用构造函数的给定参数创建一个类型为ClassName
的临时对象。因此,您并不是简单地调用构造函数;您正在创建一个对象
因此,您正在创建一个
错误
对象。您的问题是Error
的名称是impress\u errors::Error
,而不是“impress\u errors::Error::Error”。第二个::Error
似乎是试图命名构造函数。构造函数没有名称;它们不是你可以随心所欲地找到和调用的函数(同样,也不是你的意思)。这看起来像是编译器中的一个错误,拒绝了它。代码是
合法,但不是因为你认为的原因。世上没有这样的事
“显式调用构造函数(方法)”,因为构造函数不
有名称(§12.1/1)。另一方面,impress\u errors::Error::Error
是类型的名称;类名注入(§9/2)表示该类
impress\u errors::Error
包含中的名称声明Error
类,作为类外名称的同义词。所以
impress\u errors::Error
,impress\u errors::Error::Error
,
impress\u errors::Error::Error
等。所有名称都是相同的类型
(虽然只有第一个是惯用的,但其余的都是多余的
噪音)。当类型的名称后跟括号时
表达式列表,就像这里的情况一样,它是一个“显式类型”
转换(函数表示法)”。(§5.2.3-标准中规定
是显式类型转换,即使表达式列表为空,或
包含多个表达式不要问我“类型”是什么
在这种情况下被转换。)因此impress\u errors::Error(err\u code)
(或
impress\u errors::Error::Error(err\u code)
表示将err\u code
转换为
一个impress\u errors::Error
。在本例中,它将导致调用
构造函数,因为这是将int
转换为
impress\u errors::Error
(但是,可以构造案例
其中,编译器将调用
对象正在转换。)虽然您可以使用placement new显式调用构造函数,请参见,但您还没有用于放置对象的对象或内存块 抛出新的MyError(MyParams)
并让异常处理程序负责删除它。FWIW Microsoft将此方法用于MFC。我遇到了完全相同的错误消息 解决方案是更改此行:
throw impress_errors::Error::Error(err_code); //Call constructor explicitly
到
<>在C++中,你可以调用派生类构造函数中的基类构造函数,只是从不使用范围解析运算符::通常是坏的想法:<代码>新< /Cord>一个异常对象并期望处理程序删除它;更好地直接抛出对象并避免内存泄漏的可能性。@ James Kanze:3.3.4.3.1/2出现。换句话说。我这里没有最终标准,只有n3290,但我肯定最终文件在这个部门没有太大变化。这似乎意味着,
impress\u errors::Error::Error
不能用作类型名,尽管有注入。@n.m我在看n3291,但我不知道它如何在这里应用。§3.4.3.1/2首先说“在构造函数是可接受的查找结果的查找中[…]”,这里不是这样。那里的例子说A::A;//错误,A::A不是类型名
,为什么?它可以是另一个位置的类型名吗?我知道例子不规范,但这里的意图是什么?gcc似乎和我使用相同的解释。当它看到像A::A(7)
这样的表达式时,抱怨是双重的:(1)A::A
命名一个构造函数,并且(2)构造函数不能直接调用。也就是说,这是一个可接受的查找结果,但不符合§3.4.3.1/2中的使用限制。另请参见5.1.1/8:其中使用了类名::类名,并且两个类名引用同一个类,此符号命名构造函数(12.1).
将其与命名析构函数的A::~A
表示法进行比较。尽管构造函数和析构函数都没有名称,但这一点仍然存在。
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;
}
throw impress_errors::Error::Error(err_code); //Call constructor explicitly
throw impress_errors::Error(err_code); //Call constructor explicitly