2017-01-18 46 views
-1

我想修改PierreBdR's exception example如何製作自定義異常,以便其他類可見。他的例子適用於我,但例外情況僅在該類中可見。C++在hpp文件中聲明異常

我使用MS Visual Studio 2013,我是一個C++新手,受到Java心態的阻礙。

這裏是什麼在.HPP文件:


struct IllegalArgumentException : public std::exception 
{ 
public: IllegalArgumentException(std::string ss); 
public: ~IllegalArgumentException(); 

const char* IllegalArgumentException::what() { return s.c_str(); } 

private: std::string s; 

}; 

這裏是.cpp文件的一部分:

 

IllegalArgumentException::IllegalArgumentException(std::string ss) : s(ss) {} 

IllegalArgumentException::~IllegalArgumentException() {} 

const char * IllegalArgumentException::what() { return s.c_str(); } 

我越來越:

  • 錯誤C2011 :'IllegalArgumentExcpetion':'struct'類型重定義(.hpp文件)
+1

首先,你的cpp文件中的what()應該是IllegalArgumentException :: what()。 – 0x5453

+0

@ 0x5453,謝謝。修改代碼後,只剩下一個錯誤。 – ssimm

+2

你忘記了標題周圍的守衛。 –

回答

1

您混淆了what()函數的聲明和定義。您嘗試使用範圍分辨率運算符(即::)引用該函數。在這種情況下,應該在定義(即在.cpp文件)

另外,what()功能是在你的.HPP文件實現爲內嵌函數來完成的,這意味着你不需要在.cpp文件中再次定義它。因此你得到了一個redefinition of ‘const char* IllegalArgumentException::what()錯誤。

P.S:在C++類聲明中,不需要指定每個屬性/方法的訪問修飾符,只需在一個修改器中對它們進行分組即可。

.HPP文件:

struct IllegalArgumentException : public std::exception 
{ 
public: 
IllegalArgumentException(std::string ss); 
~IllegalArgumentException(); 

const char* what() { return s.c_str(); } 

private: 
std::string s; 

}; 

cpp文件:如果一個或classstruct內聲明

IllegalArgumentException::IllegalArgumentException(std::string ss) : s(ss) {} 

IllegalArgumentException::~IllegalArgumentException() {} 
0

我不知道,但我可以發表評論......如此

我想你「是什麼」的功能是實現了兩個時代: 首先在你的HPP文件,然後在cpp文件。

2

點1

const char* IllegalArgumentException::what() { return s.c_str(); } 

被錯誤地聲明。由於聲明是在IllegalArgumentException類,IllegalArgumentException:: is implied內部編譯的,因爲編譯器現在認爲你在聲明別的東西。你想

const char* what() { return s.c_str(); } 

此外,{ return s.c_str(); }部分實現的功能,所以沒有必要實現它在cpp文件。

點2

struct一切public除非宣佈繼private關鍵字。除非另有說明,否則這與class相反,其中一切均爲private。一個class和一個struct幾乎是相同的,除了默認訪問的區別。

點3

在C++中,您可以聲明區塊中成員的訪問級別。不需要一次一個地聲明成員的訪問級別。

struct IllegalArgumentException : public std::exception 
{ 
    // these are all public by default in a struct 
    IllegalArgumentException(std::string ss); 
    ~IllegalArgumentException(); 
    const char* IllegalArgumentException::what() { return s.c_str(); } 
private: // everything after this is private 
    std::string s; 
    int example; 
}; 

class IllegalArgumentException : public std::exception 
{ 
public: // these are all private by default in a class and need to be public 
    IllegalArgumentException(std::string ss); 
    ~IllegalArgumentException(); 
    const char* IllegalArgumentException::what() { return s.c_str(); } 
private: // switch back to private 
    std::string s; 
    int example; 
}; 

class IllegalArgumentException : public std::exception 
{ 
    // these are all private by default in a class 
    std::string s; 
    int example; 
public: // everything after this is public 
    IllegalArgumentException(std::string ss); 
    ~IllegalArgumentException(); 
    const char* IllegalArgumentException::what() { return s.c_str(); } 
}; 

4點

IllegalArgumentException::~IllegalArgumentException() {} 

沒有做任何事情。它不需要做任何事情,所以Rule of Zero建議不要有析構函數。編譯器會爲你創建它。如果你不必寫它,不要寫它,因爲不存在的代碼沒有錯誤。

class IllegalArgumentException : public std::exception 
{ 
    // these are all private by default 
    std::string s; 
    int example; 
public: // everything after this is public 
    IllegalArgumentException(std::string ss); 
    const char* IllegalArgumentException::what() { return s.c_str(); } 
}; 

點5

從KerrekSB這裏偷竊,因爲它是一個點,OP對另外一個問題。 Use Include Guards

包含防護功能可防止在同一translation unit中多次包含標題。這是一個問題,因爲膨脹和同一事物被定義或聲明的可能性不止一次,導致混淆真實的問題。

一個簡單的頭文件保護:

#ifndef ILLEGALARGUMENTEXCEPTION_H // if we've never seen ILLEGALARGUMENTEXCEPTION_H 
            // before, do the following 
#define ILLEGALARGUMENTEXCEPTION_H // OK we've seen it now! 

// all subsequent includes of IllegalArgumentException.h will have seen 
// ILLEGALARGUMENTEXCEPTION_H and fail the ifndef, skipping everything 
// until it finds the closing #endif 

#include <string> 
#include <exception> 
class IllegalArgumentException : public std::exception 
{ 
    // these are all private by default 
    std::string s; 
    int example; 
public: // everything after this is public 
    IllegalArgumentException(std::string ss); 
    const char* IllegalArgumentException::what() { return s.c_str(); } 
}; 

#endif // end of Include Guard 

您也可以使用#pragma once,但警告說,#pragma意味着非標準編譯器擴展。編譯器可能不存在once,如果不存在,編譯器可以不告訴你跳過指令

once不在標準中有很多原因,最重要的是它有unresolved fail cases。謹慎使用它。

+0

你給我所有這些好的提示是非常友好的(我已經重讀過幾次)。但是我必須獎勵czimbortibor的答案,因爲他的答案更符合極簡主義和可驗證的理想。 – ssimm

+0

@ssimm不是問題。與問題直接相關的唯一一點是第1點,czimbortibor更詳細地解釋了這一點。 – user4581301

0

看起來你可能或許間接地多次包括.hpp文件?

#include是在幾個.cpp文件之間共享代碼的一種相當原始的方式:它告訴編譯器(特別是預處理器)在代碼中的那個位置導入.hpp的內容。然後在稍後的過程中,編譯器會將整個事物編譯爲一個文件。 (對於該預處理步驟,有一個完整的瘋狂圖靈完整語言; IMO應該儘可能避免它,大多數情況下只用於本說明中概述的內容。)

這種方法的一個問題是,如果最終導入一個.hpp文件不止一次 - 這是一個非常常見的操作,因爲.hpp文件通常包含其他.hpp文件 - 您將重複該代碼。定義一個結構或類不止一次是非法的,所以你會得到關於「類型重定義」的錯誤。

解決方法是在每個.hpp文件中使用include guard。在最高層,用線,如:

#ifndef SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER 
#define SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER 

然後在.HPP文件的最底部:

#endif // SOME_STRING_THAT_UNIQUELY_IDENTIFIES_THIS_HEADER 

這些預處理指令,#ifndef#define等將刪除中間的任何文字如果大的唯一字符串已經定義。通常你的代碼庫會爲這個大字符串建立約定,比如編碼路徑。我的公司甚至使用lint工具來確保您編碼正確。

這確保瞭如果您#include .hpp兩次,或者#include包含已包含的.hpp的另一個.hpp,您將在最終的預處理器輸出中獲取.hpp文件的內容。

這個和一般的預處理器是真正展示它的年代的C++中不太有魅力的部分之一。很快,這種語言將會獲得一個更加現代和舒適的系統來共享稱爲「模塊」的界面。同時,每個.hpp需要這三行樣板。

+0

ht。 Kerrek SB和其他推斷失蹤的人包括警衛。 – ech