如何正確的過載類型別中char*強制型別轉換符?
阿新 • • 發佈:2021-01-06
技術標籤:C++ 模板超程式設計指標c++棧類
過載類型別強制轉換符時的注意事項
以將類型別強制轉換為char*型別為例,我們都知道強制轉換為char*型別,無非就是過載operator char*(),但是我們經常沒注意的是,當我們進行了如下程式設計,會出現出乎意料的現象(錯誤示例):
#include<iostream> usingnamespacestd; #include<sstream> #include<string> classPerson { private: stringname; intage; public: Person()=default; Person(stringname,intage); Person(Person&obj); operatorchar*(); ~Person()=default; }; Person::Person(stringname,intage) { this->name=name; this->age=age; } Person::Person(Person&obj) { this->name=obj.name; this->age=obj.age; } Person::operatorchar*() { ostringstreamsstr; sstr<<this->name<<"的年齡為"<<this->age; returnconst_cast<char*>(sstr.str().c_str()); } intmain() { PersonPerson_Obj1("張三",19); cout<<Person_Obj1<<endl; }
輸出結果:(全是亂碼)
我們探究一下原因:
導致這樣的原因,是因為我們返回的是一個指向暫時記憶體空間的char*指標,也就是說當我們將返回的char*型別的指標(注:當我們過載了char*強制轉換符,類型別物件在cout輸出時會隱式轉換為char*變數進行輸出)進行cout輸出之前,char*型別指標指向的記憶體空間早已被釋放掉,如下示例:
#include<iostream> usingnamespacestd; #include<sstream> #include<string> char*ShowInf() { ostringstreamsstr("張三"); returnconst_cast<char*>(sstr.str().c_str());//返回指向臨時儲存空間的char*型指標 } intmain() { cout<<ShowInf()<<endl;// 輸出之前伴隨著ShowInf()函式生命的結束裡面的臨時變數已經被銷燬 }
輸出結果:(輸出亂碼)
因此,我們對過載程式做如下改進:
我們在類型別中新增一個新的變數,這個變數的型別和我們要過載的強制型別轉換符的返回值一致,即
我要過載char*型別的強制型別轉換符,那我就在類型別中定義一個專門定義一個char*的變數,以供儲存被強制型別轉換後的結果。
#include<iostream> usingnamespacestd; #include<sstream> #include<string> classPerson { private: stringname; intage; char*Output; public: Person()=default; Person(stringname,intage); Person(Person&obj); operatorchar*(); ~Person()=default; }; Person::Person(stringname,intage) { this->name=name; this->age=age; } Person::Person(Person&obj) { this->name=obj.name; this->age=obj.age; } Person::operatorchar*() { ostringstreamsstr; sstr<<this->name<<"的年齡為"<<this->age; this->Output=newchar[sstr.str().size()]; strcpy(this->Output,sstr.str().c_str()); returnthis->Output; } intmain() { PersonPerson_Obj1("張三",19); cout<<Person_Obj1<<endl; }
輸出結果:
我們看到輸出結果正常,我們對比“改進前”與“改進後“ operator char*()中程式碼的區別:
改進前:
Person::operatorchar*()
{
ostringstreamsstr;
sstr<<this->name<<"的年齡為"<<this->age;
returnconst_cast<char*>(sstr.str().c_str()); // 返回指向臨時儲存區域的指標(臨時變數其實就是在棧(stack)當中儲存的變數,它會隨著區域性變數堆在函式的釋放而被釋放掉)
}
改進後:
Person::operatorchar*()
{
ostringstreamsstr;
sstr<<this->name<<"的年齡為"<<this->age;
this->Output=newchar[sstr.str().size()];// 動態申請記憶體空間,將資料存在堆區(heap)中
strcpy(this->Output,sstr.str().c_str());// 將臨時變數的值拷貝至堆區變數當中
returnthis->Output;// 輸出堆區變數
}
因此,我們以後切記:過載強制型別轉換符所得到的相應型別的資料應該在本類型別中存放,不應該返回臨時變數,任何返回臨時變數的操作都是不可行的。