[英]Copying similar classes in C++
我有兩個結構相似的課程。
class A{
int a;
char *b;
float c;
A(char *str) { //allocate mem and assign to b }
};
class B{
int a;
char *b;
float c;
B(char *str) { //allocate mem and assign to b }
B(B & bref) { //properly copies all the data }
};
我想將B
的對象復制到A
的對象。 以下轉換可以嗎?
A aobj("aobjstr");
B bobj("bobjstr");
bobj = aobj; //case 1
bobj = B(aobj); //case 2
案例2會奏效嗎? 當調用B的副本構造函數時, aobj
可以正確轉換並解釋為B &
?
編輯 :那呢?
B bobj(aobj)
不,如果不編寫轉換構造函數或轉換運算符,就無法在不相關的類型之間隱式轉換。 大概是您的編譯器告訴您的。 我的錯誤如下:
error: no match for ‘operator=’ in ‘bobj = aobj’
note: no known conversion for argument 1 from ‘A’ to ‘const B&’
error: no matching function for call to ‘B::B(A&)’
您可以通過給B
一個轉換構造函數來允許轉換:
class B {
// ...
B(A const & a) { /* properly copy the data */ }
};
如果您不能更改類,則將需要一個非成員函數來進行轉換。 但這只有在班級成員是公開的情況下才有可能。 在您的示例中,所有成員(包括構造函數)都是私有的,因此根本無法使用這些類。 據推測,在您的實際代碼中情況並非如此。
如果您想過着危險的生活,則可以通過將A
對象顯式重新解釋為B
來擺脫困境,因為它們都是具有相同數據成員的標准布局類型:
// DANGER: this will break if the layout of either class changes
bobj = reinterpret_cast<B const &>(a);
注意,由於您的類分配了內存,因此大概需要在其析構函數中對其進行分配。 為了避免重復刪除,您還必須按照“三則規則”正確實現復制構造函數和復制分配運算符。
如果聽起來一切都太麻煩了,為什么不使用std::string
,它可以為您管理內存呢?
如果您嘗試對其進行編譯,您會發現這些都不起作用。 一方面,您的構造函數是private
。
bobj = aobj; //case 1
這嘗試使用簽名來調用賦值運算符:
B& B::operator =(A const&)
這不存在,編譯將失敗。
bobj = B(aobj); //case 2
這將嘗試調用A::operator B()
,該命令不存在,並且編譯將失敗。
最后:
B bobj(aobj)
這將嘗試使用簽名B::B(A const&)
調用構造函數,該簽名不存在,並且編譯將失敗。
你說,
我不能更改/修改類A和B,它們是生成的。
然后要么需要修復生成器,要么必須編寫自己的適配器。
您可以考慮以下注意事項:
1) char* b
出了問題。 當您將aobj復制到bobj時,指針aobj.b
的值將被復制到bobj.b
,這意味着它們都指向相同的內存位置,並且像這樣更改一個位置: aobj.b[0] = 'Z'
將導致bobj.b
進行更改。
您可以通過將b
從指針更改為平面數組來解決此問題:
//...
char b[MAXLEN];
//...
對此的更好解決方案是定義一個構造函數(接受其他類型),並至少對類B重載賦值(=)運算符,並處理指針賦值(為新指針分配緩沖區並向其復制內容)。
2)更新:示例語法如下:
bobj = B(reinterpret_cast<B&> (aobj));
// or simply:
bobj = reinterpret_cast<B&> (aobj);
3)請注意,這很危險,不安全,因此不建議這樣做。 這意味着您的解決方案的設計可能應該更改。 例如,A和B都可以從公共基類繼承; B從A繼承; 或B顯式定義了類A的構造函數和賦值運算符。強烈建議使用它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.