2012-06-03 44 views
2

衍生我希望解決以下問題2類之間的交叉分配:我有2種類型的變量我如何防止串

class Type1Str : public string 
{ 
public: 
    Type1Str(const string & str) : string(str) {} 
}; 

class Type2Str : public string 
{ 
public: 
    Type2Str(const string & str) : string(str) {} 
}; 

我想享受一個字符串的所有好處,但防止交叉分配:

Type1Str t1; 
Type2Str t2; 
t1 = t2;       // <= should not be allowed 
Type2Str t2_1(t1);     // <= should not be allowed 
Type2Str t2_2("a string");   // <= should be allowed 

我該怎麼做?

+0

正在做作業嗎? –

+0

不幸沒有:)無論如何,都會很感激。 – OSH

+1

這不是一個真正的答案,但是...你爲什麼從std :: string中公開派生*?我可以理解私人繼承,但爲什麼是公共? –

回答

2

不幸的是,OP呈現的代碼,沒有編譯。

這裏的原始代碼以最自然的方式修正所以它編譯:

class Type1Str : public string 
{ 
public: 
    Type1Str() {} 
    Type1Str(const string & str) : string(str) {} 
}; 

class Type2Str : public string 
{ 
public: 
    Type2Str() {} 
    Type2Str(const string & str) : string(str) {} 
}; 

假設上述是什麼意思,所有的需要,以防止交叉分配是使轉換構造函數explicit

#include <string> 
using std::string; 

class Type1Str : public string 
{ 
public: 
    Type1Str() {} 
    explicit Type1Str(const string & str) : string(str) {} 
}; 

class Type2Str : public string 
{ 
public: 
    Type2Str() {} 
    explicit Type2Str(const string & str) : string(str) {} 
}; 

int main() 
{ 
    Type1Str t1; 
    Type2Str t2; 

    t1 = t2;   // A. !Invalid, involves an implicit conversion. 
    Type2Str t2_2(t1); // B. Still allowed, here the conversion is explicit. 
} 

在行標B中的調用的不實參的隱式轉換的轉換,但Type2Str的顯式轉換構造函數。實際參數t1與該構造函數的正式參數直接匹配,因爲t2 a std::string。 OP也想阻止B行。

然後,一種簡單的方法是使轉換更加明確,即命名它。

即,爲正式參數引入載體類型,或者引入額外的虛擬轉換名稱參數,或者用公共工廠函數替換公共轉換構造函數。工廠功能最簡單,並且是2012年免費的重新使用效率,但是它具有維護成本:派生類必須重新實現以提供該功能。這裏提到的其他兩種解決方案,額外的虛擬名稱參數是最容易實現的和最少的代碼:

#include <string> 
using std::string; 

namespace from { enum StdString { stdString }; }; 

class Type1Str : public string 
{ 
public: 
    Type1Str() {} 
    Type1Str(from::StdString, const string & str) : string(str) {} 
}; 

class Type2Str : public string 
{ 
public: 
    Type2Str() {} 
    Type2Str(from::StdString, const string & str) : string(str) {} 
}; 

int main() 
{ 
    Type1Str t1; 
    Type2Str t2; 
    Type2Str t3(from::stdString, t1); // OK. 

    t1 = t2;   // A. !Invalid, no conversion possible. 
    Type2Str t2_2(t1); // B. !Invalid, no conversion possible. 
} 

那麼,什麼是錯,而不是僅僅宣佈私有構造函數和賦值操作符爲所有類型的那一個想禁止直接複製?

那麼,除了發脆,對於達至O Ñ類型(Ñ )聲明。所以這通常不是一個好主意。然而,在我寫這篇文章時,OP選擇了一種解決方案「的解決方案」。只是要警告:它一般’ 真的不是一個好主意。

+0

好的,我理解了這些論點。我同意這個解決方案更好。謝謝。 – OSH

+0

btw - 在第二類定義中,你離開了「顯式」。這是爲了一個目的,還是它是一個錯字? – OSH

+0

對不起,我只是沒有看到它。在閱讀本文時可能會被刪除。 –

2

只要把構造到聲明的私有/保護部分:

class Type1Str : public string 
{ 
    Type1Str(const class Type2Str&); // use forward declaration for class Type2Str 
public: 
    Type1Str(const string & str) : string(str) {} 
}; 

class Type2Str : public string 
{ 
    Type2Str(const Type1Str&); // this does not allow 'Type2Str t2_2(t1);' 
public: 
    Type2Str(const string & str) : string(str) {} 
}; 
3

這應該做的伎倆:

#include <string> 

using namespace std; 

class Type2Str; 

class Type1Str : public string 
{ 
public: 
    Type1Str() {} 
    Type1Str(const std::string & str) : std::string(str) {} 

private: 
    Type1Str(const Type2Str &); // deliberately private and unimplemented 
    Type1Str & operator = (const Type2Str &); // deliberately private and unimplemented 
}; 

class Type2Str : public string 
{ 
public: 
    Type2Str() {} 
    Type2Str(const std::string & str) : std::string(str) {} 

private: 
    Type2Str(const Type1Str &); // deliberately private and unimplemented 
    Type2Str & operator = (const Type1Str &); // deliberately private and unimplemented 
}; 

int main(int, char **) 
{ 
    Type1Str t1; 
    Type2Str t2; 
    t1 = t2;       // <= should not be allowed 
    Type2Str t1_2(t1);     // <= should not be allowed 
    Type2Str t2_2("a string");   // <= should be allowed 
    return 0; 
} 
+0

謝謝!您的解決方案有效 – OSH

+0

@iammilind這似乎是視覺工作室太好了的另一種情況。你沒有必要做任何事情來解決這個問題。但是,相同的代碼在VS中編譯。我應該在我使用VS的問題中提及。感謝您的評論和答覆。 – OSH

+0

@OSH,其實我的看法不對。我刪除了我的回答和上面的評論。並upvoting這篇文章。 – iammilind