c++ std::invalid_argument應用

來源:互聯網
上載者:User

首先說明invalid_argument是一個類(class invalid_argument;),它的繼承關係如下

exception-------->logic_error--------->invalid_argument

invalid_argument原型是 複製代碼 代碼如下:class invalid_argument:public logic_error {
public:
explicit invalid_argument (const string& what_arg);
};

它在stdexcept標頭檔中,在std命名空間內。下面舉一個例子來使用它 複製代碼 代碼如下:#include <iostream>
#include <stdexcept>

int main(int argc,char ** argv)
{
try
{
bool errorArgument;
errorArgument=true;
if(errorArgument)
{
throw std::invalid_argument("occur error!");
}
}
catch(std::invalid_argument &ia)
{
//what()為invalid_argument繼承exception類的函數
std::cerr<<" Invalid_argument "<< ia.what()<<std::endl;
}

return 0;
}

運行結果為:

Invalid_argument occur error!那麼上面的例子是一個最簡單的應用了。invalid_argument顧名思義指無效參數,這個應該應用在檢查參數是否是無效的,一般檢查參數用於特定的函數以及類,那麼就應該是給類的成員變數賦值或者函數參數賦值時,檢查其賦給它們的值是否有效,例如有一個類(people,有三個成員變數name,age,height)那麼我們知道人的年齡在0~150歲之間(ps:如果對於程式員可以直接定義為0~75)。身高的話0~300cm,名字的長度不會超過20。如果都超過這些範圍,就可以認定是無效資料。那麼這個類可以如下定義: 複製代碼 代碼如下:#include <stdexcept>
#include <iostream>
#include <string>

class People
{
public:
People(const std::string& n,const int& a,const int& h)
:name(n),age(a),height(h)
{}

inline void set(const std::string& n,const int& a,const int& h)
{
if(!valid(n,a,h))
{
throw std::invalid_argument("People's argument is error");
}
name = n;
age = a;
height = h;
}

inline bool valid(const std::string& n, const int& a, const int& h)
{
return ( n.length() == 0 ||n.length() > 20 )&& a >= 0 && a< 150 && h > 0 && h < 300 ;
}
private:
std::string name;
int age;
int height;

};

int main(int argc, char** argv)
{
People p("Li San", 20 , 170);
try
{
p.set("Li San" , 20 ,1700);
}
catch (std::invalid_argument & ia)
{
std::cerr << "Error: " << ia.what() << std::endl;
}
return 0;
}

其運行結果為:

Error: People's argument is error上面程式只要輸入無效資料,就會輸出錯誤。但是僅僅這樣是不夠的,我們還無法定位無效參數在哪個檔案與哪個一行或者在哪個函數中,如果在列印錯誤的時候連這些資訊一併輸出相信定位問題就方便多了。那麼我們在報出錯誤資訊的時候連這些資訊也附加上就明確多了。 複製代碼 代碼如下:#include <stdexcept>
#include <iostream>
#include <string>
#define TOSTRING(x) #x

//class ErrorInfo
//{
// public:
// ErrorInfo(const std::string& f,const std::string& l,const std::string& fun)
// : file(f), line(l), func(fun)
// {}
//
// inline const std::string getFile() const
// {
// return this->file;
// }
//
// inline const std::string getLine() const
// {
// return this->line;
// }
//
// inline const std::string getFunc() const
// {
// return this->func;
// }
//
// private:
// const std::string file;
// const std::string line;
// const std::string func;
//};

class ErrorInfo
{
public:
ErrorInfo(const char * f, const char * l, const char * fun)
:file(f), line(l), func(fun)
{}

inline std::string getFile() const
{
return this->file;
}

inline std::string getLine() const
{
return this->line;
}

inline std::string getFunc() const
{
return this->func;
}
private:
const char* file;
const char* line;
const char* func;
};

std::string operator +(const std::string & str, const ErrorInfo& ei)
{
std::string strTemp(ei.getFile() + ":" + ei.getLine() + ":" + ei.getFunc());
strTemp +=str;
return strTemp;
//return str::string(ei.getFile() + ":" + ei.getLine() + ":" + ei.getFunc() += str );
}

class InvalidPeople:public std::invalid_argument
{
public:
InvalidPeople(ErrorInfo & ei)
: std::invalid_argument( "Invalid People " + ei )
{}
~InvalidPeople() throw()
{}
};

class People
{
public:
People(const std::string& n,const int& a,const int& h)
:name(n),age(a),height(h)
{}

inline void set(const std::string& n,const int& a,const int& h)
{
if(!valid(n,a,h))
{
ErrorInfo ei(__FILE__,TOSTRING(__LINE__),__PRETTY_FUNCTION__);
// ErrorInfo ei(__FILE__,#__LINE__,__PRETTY_FUNCTION__);
throw InvalidPeople(ei);
// throw InvalidPeople(ErrorInfo(__FILE__,TOSTRING(__LINE__),__PRETTY_FUNCTION__));
}
name = n;
age = a;
height = h;
}

inline bool valid(const std::string& n, const int& a, const int& h)
{
return ( n.length() == 0 ||n.length() > 20 )&& a >= 0 && a< 150 && h > 0 && h < 300 ;
}
private:
std::string name;
int age;
int height;

};

int main(int argc, char** argv)
{
People p("Li San", 20 , 170);
try
{
p.set("Li San" , 20 ,1700);
}
catch (std::invalid_argument & ia)
{
std::cerr << "Error: " << ia.what() << std::endl;
}
return 0;
}

其運行結果為:

TestError: invalid_a.cpp:__LINE__:void People::set(const std::string&, const int&, const int&)Invalid People注意:
(1)上面#define TOSTRING(x) #x就可以將int類型轉換為const char *類型。
(2) __FILE__是const char*類型,並且通過#define TOSTRING(x)轉換後的類型為const char*類型,編譯器是gun那麼擷取所在的函數名稱就是__PRETTY_FUNCTION__也是const char*類型。
可以看到__LINE__並沒有顯示出行號,這裡原因編譯器直接將__LINE__其轉換為"__LINE__"這個字串了那麼這裡如何解決呢?筆者試過好多方法,最終找出來了,我們可以在#define一次,就可以正常現實了。如下代碼 複製代碼 代碼如下:#include <stdexcept>
#include <iostream>
#include <string>
#define TTOSTRING(x) #x
#define TOSTRING(x) TTOSTRING(x)
...
...
//後面代碼與上面一樣

其運行結果為:

TestError: invalid_a.cpp:91:void People::set(const std::string&, const int&, const int&)Invalid People
至於裡面原理,為什麼兩次就能夠將__LINE__表示的數字例如(71)轉換成const char* “71”,而不是轉換成“__LINE__"const char*字串,希望清楚的園友,給出答案,謝謝!

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.