2011-09-27 56 views
2

定義構造對象:通過調用構造函數(方法)類的明確

#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. 當我顯式調用創建對象的構造函數時會發生什麼?這是對的嗎?
爲什麼這是行得通的?

回答

0

它應該可以,如果你做什麼編譯器問你。只要刪除一個「錯誤」語句;>我不知道爲什麼這改變了gcc,但class_name :: construction_name只是多餘的。編譯器知道你想調用構造函數,因爲它的名字與類的名字相同

5

你沒有調用構造函數(當然,你是,但不是你的意思)。語法ClassName(constructor params)表示使用給定參數作爲其構造函數,創建ClassName類型的臨時對象。所以你不是簡單地調用構造函數;你正在創建一個對象。

因此您正在創建一個Error對象。你的問題是,Error的名稱是impress_errors::Error,而不是「impress_errors :: Error :: Error」。第二個::Error似乎是一個嘗試命名構造函數。構造函數沒有名字;他們不是你可以隨心所欲地找到和調用的功能(再次,不是你的意思)。

1

這看起來像編譯器中的一個錯誤,拒絕它。代碼爲 合法,但不是您認爲的理由。 「 」沒有明確地調用構造函數(方法)「,因爲構造函數不包含名稱(§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不是類型名稱,爲什麼?它可以是另一個位置的類型名稱嗎?我知道例子不是規範的,但是這裏的意圖是什麼? –

0

儘管您可以使用placement new顯式調用構造函數,請參見placement operators,但您沒有用於放置對象的對象或內存塊。可能更容易使用像

扔新MyError(MyParams);

並使異常處理程序負責刪除它。 FWIW微軟在MFC中使用這種方法。

+0

通常new''new異常對象是個壞主意,希望處理程序刪除它;更好地直接拋出對象並避免內存泄漏的可能性。 –

0

我遇到了完全相同的錯誤消息。

解決的辦法是改變這一行:

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

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

在C++中,你可以調用派生類構造函數中的基類的構造函數,只是從來沒有使用範圍解析操作: :

相關問題