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