通过调用构造函数(方法)类的明确

通过调用构造函数(方法)类的明确

问题描述:

定义构造对象:通过调用构造函数(方法)类的明确

#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的唯一途径。(这是可能的,然而,构造个案 ,其中编译器将调用 对象上的用户定义的转换函数)

+0

@James Kanze:§3.4.3.1/ 2似乎另有说明。我在这里没有最终的标准,只有n3290,但我确信最终文件在这个部门没有太大变化。这似乎意味着'impress_errors :: Error :: Error'不能用作类型名称,尽管注入。 –

+0

@n.m我正在看n3291,但我不明白它在这里如何应用。 §3.4.3.1/ 2首先说“在构造函数是一个 可接受的查找结果[...]”的查找中,在这里不是这种情况。 –

+0

那里的例子说'A :: A a; //错误,A :: A不是类型名称,为什么?它可以是另一个位置的类型名称吗?我知道例子不是规范的,但是这里的意图是什么? –

尽管您可以使用placement new显式调用构造函数,请参见placement operators,但您没有用于放置对象的对象或内存块。可能更容易使用像

扔新MyError(MyParams);

并使异常处理程序负责删除它。 FWIW微软在MFC中使用这种方法。

+0

通常new''new异常对象是个坏主意,希望处理程序删除它;更好地直接抛出对象并避免内存泄漏的可能性。 –

我遇到了完全相同的错误消息。

解决的办法是改变这一行:

throw impress_errors::Error::Error(err_code); //Call constructor explicitly 

throw impress_errors::Error(err_code); //Call constructor explicitly 

在C++中,你可以调用派生类构造函数中的基类的构造函数,只是从来没有使用范围解析操作: :