通过显式调用构造函数(方法)来构造对象

时间:2011-09-27 07:49:00

标签: 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();
    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. 当我明确地调用构造函数来创建对象时会发生什么?这是正确的吗? 为什么这有效呢?

5 个答案:

答案 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::Errorimpress_errors::Error::Errorimpress_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 ++中,您可以在派生类构造函数中调用基类构造函数,只是从不使用范围解析运算符::