Chinaunix首页 | 论坛 | 博客
  • 博客访问: 156886
  • 博文数量: 31
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 360
  • 用 户 组: 普通用户
  • 注册时间: 2017-02-28 08:37
个人简介

没有绝活,怎能风骚.....

文章分类

全部博文(31)

文章存档

2017年(31)

我的朋友

分类: C/C++

2017-04-23 23:54:46

1.编写类String拷贝构造函数赋值函数等(可以调用C++/C的字符串库函数)(10)

已知类String的原型为:

class String

{

 public:

   String(const char *str = NULL); // 普通构造函数

   String(const String &other); // 拷贝构造函数

   ~ String(void);                  // 析构函数

   String & operator =(const String &other); // 赋值函数

private:

  char *m_data;                  // 用于保存字符串

};

请编写String的上述4个函数。

    我们都知道,构造函数、析构函数与赋值函数是每个类最基本的函数。每个类只有一个析构函数和赋值函数,但可以有多个构造函数(包括一个拷贝构造函数,其他的称为普通构造函数)。对于任意一个类A,如果不编写上述函数,C++编译器将会自动为A产生4个缺省的函数,如:
    A(void);//缺省的无参数构造函数
    A(const A &a);//缺省的拷贝构造函数
    ~A(void);//缺省的析构函数
    A & operator=(const A &a);//缺省的赋值函数
    所以很多人都有疑惑,既然能自动生成函数,为什么还要程序员编写?原因是:
        ①如果使用“缺省的无参数构造函数”和“缺省的析构函数”,等于放弃了自主“初始化”和“清除”的机会;
        ②“缺省的拷贝构造函数”和“缺省的赋值函数”均采用“位拷贝”而非“值拷贝”的方式来实现,倘若类中含有指针变量,这两个函数注定将出错。
    根据题目要求,要我们自己编写普通构造函数、拷贝构造函数、析构函数和赋值函数。
    构造函数:其功能是在创建一个新的对象的时候给数据成员赋初值,也就是给对象做初始化。
    析构函数:其功能则是用来释放一个对象,在对象删除之前用它来做一些内存释放等的清理工作,与构造函数的功能相反。
    类的构造函数和析构函数的典型应用:在构造函数中用new来为指针成员开辟一个独立的动态内存空间,而在析构函数中用delete来释放它。
 那什么是拷贝构造函数呢?
 首先对普通类型的对象来说,它们之间的复制很简单的:
    int a = 100;
    int b = a;
 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。所以就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。它是一种特殊的构造函数,函数名称必须和类名称一致,它必须的一个参数是本类型的一个引用变量。
     拷贝构造函数与赋值函数的区别?
    (1)首先在看到“=”操作符为对象赋值的时候,
          如果在对象定义时(Test B = (Test)c),此时调用拷贝构造函数;
          如果不是在对象定义赋值时(B = c),此时调用赋值函数。
     注:构造函数、拷贝构造函数,带有构造两个字,顾名思义,就是在对象声明或定义时才会使用。
     (2)内存空间角度:         
          ①拷贝构造函数的使用,是在建立对象时;当时对象没有占有内存,故不需要释放内存,不重新建立内存空间。
          ②赋值函数的使用,是 在对象建立后,当时对象已经占有内存,故需要释放先前内存,然后重新获取内存空间。

     经调试好的代码如下:

点击(此处)折叠或打开

  1. #include <iostream>
  2. #include <cstring>

  3. using namespace std;

  4. class String
  5. {
  6.     public:
  7.         String(const char *str = NULL);//普通构造函数
  8.         String(const String &other);//拷贝构造函数
  9.         ~String(void);//析构函数
  10.         String& operator=(const String &other);//赋值函数
  11.     private:
  12.         char *m_data;//用来保存字符串
  13. };
  14. /*
  15.  *定义析构函数是为了防止内存泄漏,当一个String对象超出
  16.  *它的作用域时,析构函数就会释放它所占用的内存
  17. */
  18. String::~String(void)
  19. {
  20.     cout<<"Destructing"<<endl;
  21.     if(NULL != m_data)
  22.     {
  23.         delete []m_data;
  24.         m_data = NULL;
  25.     }
  26. }
  27. /*
  28.  *普通构造函数
  29.  *构造函数首先根据一个字符串常量创建一个String对象
  30.  *这个构造函数首先分配了足够的内存,然后把这个字符串常量复制到这块内存
  31. */
  32. String::String(const char *str)
  33. {
  34.     cout<<"Constructing"<<endl;
  35.     if(NULL == str)
  36.     {
  37.         m_data = new char[1];
  38.         *m_data = '\0';
  39.     }
  40.     else
  41.     {
  42.         m_data = new char[strlen(str) + 1];
  43.         strcpy(m_data,str);
  44.     }
  45. }
  46. /*
  47.  *拷贝构造函数
  48.  *所有需要分配系统资源用户定义类型都需要一个拷贝构造函数
  49.  *它可以在函数中以传值的方式传递一个String类型的参数
  50.  *并且当一个函数以值的形式返回给String对象时实现“返回时复制”
  51. */
  52. String::String(const String &other)
  53. {
  54.     cout<<"Constructing copy"<<endl;
  55.     m_data = new char[strlen(other.m_data) + 1];
  56.     strcpy(m_data,other.m_data);
  57. }
  58. /*
  59.  *赋值函数
  60.  *赋值函数实现字符串的传值活动
  61. */
  62. String & String::operator=(const String &other)
  63. {
  64.     cout<<"Operate = Function"<<endl;
  65.     if(this == &other)//检查自赋值
  66.     {
  67.         return *this;
  68.     }
  69.     delete []m_data;//释放堆内存
  70.     m_data = new char[strlen(other.m_data) + 1];//分配新的内存资源并复制其内容
  71.     strcpy(m_data,other.m_data);
  72.     return *this;//返回本对象的引用
  73. }

  74. int main(int argc, const char *argv[])
  75. {
  76.     String a("hello");//调用普通构造函数
  77.     String b("world");//调用普通构造函数
  78.     String c(a);//调用拷贝构造函数
  79.     c = b;//调用赋值函数
  80.     return 0;
  81. }





阅读(2496) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~