2013-03-13 122 views
0

我們的教授在線發佈了一個自定義的「字符串」模板文件,並要求我們前一段時間填寫下面的函數。我的問題,爲了試圖理解這一點,爲什麼前三名的構造函數有Text = NULL;及其以下,this = source;,它的一些其他形式。我覺得每個人都應該說Text = the_input_parameter爲什麼這個構造函數是這樣寫的?

非常感謝,下面的代碼:

class String 
{ 
public: 
    // Default constructor 
    String() 
    { 
     Text = NULL; 
    } 
    String(const String& source) 
    { 
     Text = NULL; 
     // Call the assignment operator to perform deep copy 
     *this = source;  
    } 
    String(const char* text) 
    { 
     Text = NULL; 
     // Call the assignment operator to perform deep copy 

     *this = text; 

    } 
~String() 
    { 
     delete[] Text; 
    } 

    // Assignment operator to perform deep copy 
    String& operator = (const char* text) 
    { 
     // Ddispose of old Text 
     delete[] Text; 

     // +1 accounts for NULL-terminator 
     int trueLength = GetLength(text) + 1; 

     // Dynamically allocate characters on heap 
     Text = new char[trueLength]; 

     // Copy all characters from source to Text; +1 accounts for NULL-terminator 
     for (int i = 0; i < trueLength; i++) 
      Text[i] = text[i]; 

     return *this; 
    } 

    // Returns a reference to a single character from this String 
    char& operator [] (int index) const 
    { 
     int length = GetLength(); 

     // Check for valid index 
     if ((index < 0) || (index > length)) 
     { 
      stringstream error; 
      error << "operator[] - index " << index << " is out of bounds (0.." << (length - 1) << ")"; 
      throw String(error.str().c_str()); 
     } 

     return Text[index]; 
    } 
private: 
    // The encapsulated C-string 
    char* Text; 
}; 
+0

你知道深拷貝和淺拷貝之間的區別嗎? (另外,我希望你瞭解ctor初始化列表,授權構造函數等等) – 2013-03-13 20:19:17

+7

在純粹的褻瀆什麼邪惡的坑裏你挖出這個代碼嗎?構造函數是這樣寫的,因爲做這件事的人不知道他們在做什麼! – 2013-03-13 20:19:36

+3

我必須同意@CrazyEddie:在賦值方面實現構造函數是屁股倒退。我曾經不得不維護一些代碼。這是酷刑。 – 2013-03-13 20:23:48

回答

1

這只是一個分解出公共代碼到一個輔助函數的方式。在這種情況下,operator=()充當助手功能。它的功能是釋放當前字符串(在本例中爲NULL)並執行右側的深層複製。

我覺得每個人都應該說Text = the_input_parameter

對於String(const String& source)由於source不是正確的類型,所以不能編譯。

對於String(const char* text)這將是不正確的,因爲這隻會分配指針而不是執行深度複製。

上面假設您只向我們展示了類的一部分,並且實際的類定義了適當的賦值運算符和析構函數。如果沒有,你需要一位新教授。

+0

這種關係至少應該是倒置的,以便賦值運算符利用構造而不是其他方式。 – 2013-03-13 20:21:26

+0

所有的函數最初都是在頭文件中聲明的,然後在.cpp文件中實現。爲了讓自己更簡單,我將它們全部移到了頭文件中。這會解釋嗎? 至於賦值運算符和析構函數,是的,它有它們。我不認爲他們純粹要求建設者是相關的。雖然它有人竊聽,所以我會發布他們:) – Reciever80 2013-03-13 20:26:39

+2

@DrewDormann:因爲如果你沒有在構造函數中將'Text'初始化爲NULL,'operator ='後面會調用'delete [ ]在一些隨機指針上。 – 2013-03-13 20:45:59

6

爲什麼你不應該在分配方面實現的構造函數:

  • 它得到在派生類中非常討厭。想想看。
  • 很難確保異常安全。
  • 這也是低效率,啓動(需要默認構造,然後分配)。

因此,答案爲什麼它’ S DONE這樣在你的示例代碼,可能是你的教授沒有按’噸知道diddly關於C++編程。

否則,很難說:它根本沒有任何意義。


走另一條路,然而,也就是在實現複製構造方面的副本任務,是很常見的,被稱爲在複製和交換成語

很簡單,例外安全而且高效,並且是這樣的:

class Foo 
{ 
public: 
    void swap_with(Foo& other) throw() 
    { 
     // No-throwing swap here. 
    } 

    void operator=(Foo other) 
    { 
     other.swap_with(*this); 
    } 
}; 

燁,僅此而已。

變體包括命名交換器只是swap,並讓賦值操作符返回一個引用,有些更喜歡通過引用傳遞參數,然後複製(使用複製構造)。

+0

你能澄清一下你的意思是「按照任務實現構造函數」嗎?對不起,這是我問爲什麼的一部分。 – Reciever80 2013-03-13 20:37:19

+1

@ Reciever80:當然。 「在賦值方面實現構造函數」僅僅意味着構造函數將複製賦值操作符稱爲作業。相反,複製賦值運算符應該調用複製構造函數來完成這項工作。上面顯示的代碼更聰明一些。它允許調用賦值運算符的代碼調用複製構造函數(用於傳值參數),但它的原理相同:賦值應該通過構造完成。 – 2013-03-13 20:39:08

0

該類管理內存,所以析構函數釋放它,賦值操作符爲新數據分配新的數據並釋放舊數據(應該按照該順序)。

然後,初始分配的說明很清楚:您需要將成員字段初始化爲正確的值,否則它將包含垃圾(某些指向某處的指針),哪些代碼將嘗試使用並釋放。

雖然從代碼中看不到,但也可能會分配const String&和類型轉換運算符operator const char *() const

相關問題