类只是将成员函数和成员变量放到一起吗?肯定不是的,本次主要讨论构造函数和析构函数

构造函数

Different from struct in C, a constructor will be invoked when creating an object of a class.

  • struct in C: allocate memory
  • class in C++: allocate memory & invoke a constructor 调用构造函数

构造函数的作用:就是对对象的数据进行初始化。

But … No constructor is defined explicitly in previous examples. The compiler will generate one with empty body

  1. class Student
  2. {
  3. private:
  4. // ...
  5. public:
  6. // 构造函数 1
  7. Student()
  8. {
  9. name[0] = 0;
  10. born = 0;
  11. male = false;
  12. }
  13. // 构造函数2
  14. Student(const char * initName, int initBorn, bool isMale)
  15. {
  16. setName(initName);
  17. born = initBorn;
  18. male = isMale;
  19. }
  20. // The members can also be initialized as follows
  21. // born 初始化为0,male初始化为true
  22. Student(const char * initName): born(0), male(true)
  23. {
  24. setName(initName);
  25. }
  26. };

构造函数特点:

  1. The same name with the class. 要跟类名完全一样
  2. Have no return value . 没有返回值

构造函数可有多个,只要参数不同就可以。

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. class Student
  5. {
  6. private:
  7. char name[4];
  8. int born;
  9. bool male;
  10. public:
  11. Student()
  12. {
  13. name[0] = 0;
  14. born = 0;
  15. male = false;
  16. cout << "Constructor: Person()" << endl;
  17. }
  18. Student(const char *initName) : born(0), male(true)
  19. {
  20. setName(initName);
  21. cout << "Constructor: Person(const char, int , bool)" << endl;
  22. }
  23. Student(const char *initName, int initBorn, bool isMale)
  24. {
  25. setName(initName);
  26. born = initBorn;
  27. male = isMale;
  28. cout << "Constructor: Person(const char, int , bool)" << endl;
  29. }
  30. void setName(const char *s)
  31. {
  32. strncpy(name, s, sizeof(name));
  33. }
  34. void setBorn(int b)
  35. {
  36. born = b;
  37. }
  38. // the declarations, the definitions are out of the class
  39. void setGender(bool isMale);
  40. void printInfo();
  41. };
  42. void Student::setGender(bool isMale)
  43. {
  44. male = isMale;
  45. }
  46. void Student::printInfo()
  47. {
  48. std::cout << "Name: " << name << std::endl;
  49. std::cout << "Born in " << born << std::endl;
  50. std::cout << "Gender: " << (male ? "Male" : "Female") << std::endl;
  51. }
  52. int main()
  53. {
  54. Student yu;
  55. yu.printInfo();
  56. yu.setName("Yu");
  57. yu.setBorn(2000);
  58. yu.setGender(true);
  59. yu.printInfo();
  60. Student li("li");
  61. li.printInfo();
  62. Student xue = Student("XueQikun", 1962, true);
  63. //a question: what will happen since "XueQikun" has 4+ characters?
  64. xue.printInfo();
  65. Student *zhou = new Student("Zhou", 1991, false);
  66. zhou->printInfo();
  67. delete zhou;
  68. return 0;
  69. }

Destructors 析构函数

  • The destructor will be invoked when the object is destroyed. 对象被销毁的时候,被调用,
  • Be formed from the class name preceded by a tilde (~) . 析构函数之前,类名之前加上~
  • Have no return value, no parameters . 析构函数不能重载,只能有一个,且没有参数和返回值 ```cpp class Student { // … public: Student() {

      name = new char[1024]{0};
      born = 0;
      male = false;
      cout << "Constructor: Person()" << endl;
    

    }

    // 析构函数 ~Student() {

      delete [] name;  // 释放内存,还有一些关闭文件,断掉网络等操作
    

    } };

```cpp
#include <iostream>
#include <cstring>

using namespace std;

class Student
{
private:
    char *name;
    int born;
    bool male;

public:
    Student()
    {
        name = new char[1024]{0};
        born = 0;
        male = false;
        cout << "Constructor: Person()" << endl;
    }
    Student(const char *initName, int initBorn, bool isMale)
    {
        name = new char[1024];
        setName(initName);
        born = initBorn;
        male = isMale;
        cout << "Constructor: Person(const char, int , bool)" << endl;
    }

    // 析构函数
    ~Student()
    {
        cout << "To destroy object: " << name << endl;
        delete[] name;
    }

    void setName(const char *s)
    {
        strncpy(name, s, 1024);
    }
    void setBorn(int b)
    {
        born = b;
    }
    // the declarations, the definitions are out of the class
    void setGender(bool isMale);
    void printInfo();
};

void Student::setGender(bool isMale)
{
    male = isMale;
}
void Student::printInfo()
{
    std::cout << "Name: " << name << std::endl;
    std::cout << "Born in " << born << std::endl;
    std::cout << "Gender: " << (male ? "Male" : "Female") << std::endl;
}

int main()
{
    {
        Student yu;
        yu.printInfo();

        yu.setName("Yu");
        yu.setBorn(2000);
        yu.setGender(true);
        yu.printInfo();
    }
    Student xue = Student("XueQikun", 1962, true);
    xue.printInfo();

    Student *zhou = new Student("Zhou", 1991, false);
    zhou->printInfo();
    delete zhou;

    return 0;
}

当对象在其作用域结束之后,会调用析构函数进行销毁。这也是63行加入{}的演示原因。
zhou是动态申请的,如果没有delete zhou;,不会调用析构函数

#include <iostream>
#include <cstring>

using namespace std;

class Student
{
private:
    char *name;
    int born;
    bool male;

public:
    Student()
    {
        name = new char[1024]{0};
        born = 0;
        male = false;
        cout << "Constructor: Person()" << endl;
    }
    Student(const char *initName, int initBorn, bool isMale)
    {
        name = new char[1024];
        setName(initName);
        born = initBorn;
        male = isMale;
        cout << "Constructor: Person(const char, int , bool)" << endl;
    }
    ~Student()
    {
        cout << "To destroy object: " << name << endl;
        delete[] name;
    }

    void setName(const char *s)
    {
        strncpy(name, s, 1024);
    }
    void setBorn(int b)
    {
        born = b;
    }
    // the declarations, the definitions are out of the class
    void setGender(bool isMale);
    void printInfo();
};

void Student::setGender(bool isMale)
{
    male = isMale;
}
void Student::printInfo()
{
    std::cout << "Name: " << name << std::endl;
    std::cout << "Born in " << born << std::endl;
    std::cout << "Gender: " << (male ? "Male" : "Female") << std::endl;
}

int main()
{
    Student *class1 = new Student[3]{
        {"Tom", 2000, true},
        {"Bob", 2001, true},
        {"Amy", 2002, false},
    };

    class1[1].printInfo();
    delete class1;
    // delete []class1;

    return 0;
}

What is the difference between the following two lines?

delete class1;

delete []class1;

delete class1;:可以释放掉数组的空间,但是只会调用第一个对象Tom 的析构函数,第二个Bob 和第三个对象Amy 的析构不会被调用
delete []class1;:不仅会释放内存,还会将class数组的三个对象的析构函数都会调用。

所以,当new一个数组时,在delete时要加上[]