2013-03-13 129 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

相关问题