【C++初阶学习】C++类和对象-渐入之章(中2)

简介: 【C++初阶学习】C++类和对象-渐入之章(中2)
  1. 成员变量的命名风格


对于一般的命名来说在一定的情况中可能或造成命名冲突


  • 示例:


class Date
{
public:
  Date(int year)
  {
    // 这里的year到底是成员变量,还是函数形参?指定不明,编译器会根据就近原则选择是函数形参变量
    year = year;
  }
private:
  int year;
};


image.png


  • 命名风格1:


class Date
{
public:
  Date(int year)
  {
    _year = year;
  }
private:
  int _year;
};


  • 命名风格2:


class Date
{
public:
  Date(int year)
  {
    m_year = year;
  }
private:
  int m_year;
};


四、析构函数


引入:

和构造函数一样,因为一些类型的创建后需要自行释放动态开辟的空间(避免内存泄漏),为了避免忘记,C++也引入了析构函数


概念:

析构函数不是完成对象的销毁,局部对象销毁工作是由编译器完成的,而对象在销毁时会自动调用析构函数,完成类的一些资源清理工作(释放动态开辟的空间)


特性:


析构函数名是在类名前加上字符 ~


无参数无返回值


一个类有且只有一个析构函数,若未显式定义,系统会自动生成默认的析构函数(不能重载)


对象生命周期结束时,C++编译系统系统自动调用析构函数 (在C语言上的优化)


示例:


typedef int DataType;
class SeqList
{
public:
  SeqList(int capacity = 10)//构造函数
  {
    _pData = (DataType*)malloc(capacity * sizeof(DataType));
    assert(_pData);
    _size = 0;
    _capacity = capacity;
  }
  ~SeqList()//析构函数
  {
    cout << "~SeqList()" << endl;
    if (_pData)
    {
      free(_pData); // 释放堆上的空间
      _pData = NULL; // 将指针置为空
      _capacity = 0;
      _size = 0;
    }
  }
private:
  int* _pData;
  size_t _size;
  size_t _capacity;
};
int main()
{
  SeqList sl;
  return 0;
}


image.png


  1. 对于编译器生成的默认析构函数,对于内置类型不用处理(对象生命周期结束会自动销毁),对自定类型成员调用它的析构函数


注:一般来说如果成员变量没有动态开辟的空间,可以不用自己写,编译器自动生成的就足够用


  • 示例:


class String
{
public:
  String(const char* str = "jack")
  {
    _str = (char*)malloc(strlen(str) + 1);
    strcpy(_str, str);
  }
  ~String()
  {
    cout << "~String()" << endl;
    free(_str);
  }
private:
  char* _str;
};
class Person
{
private:
  String _name;
  int _age;
};
int main()
{
  Person p;
  return 0;
}


image.png


五、拷贝构造函数


概念:


在创建对象时,创建一个与一个对象一某一样的新对象


只有单个形参,该形参是对本 类类型对象的引用**(一般常用const**修饰),在用已存在的类类型对象创建新对象时由编译器自动调用


特征:


拷贝构造函数是构造函数的一个重载形式(参数不同)


拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用(传值也是一种拷贝,会继续调用拷贝函数)


示例:


class Date
{
public:
  Date(int year = 1900, int month = 1, int day = 1)//构造函数
  {
    _year = year;
    _month = month;
    _day = day;
  }
  Date(const Date& d)//拷贝构造函函数
  {
    _year = d._year;
    _month = d._month;
    _day = d._day;
  }
private:
  int _year;
  int _month;
  int _day;
};
int main()
{
  Date d1;//调用构造函数
  Date d2(d1);//调用拷贝构造函数
  return 0;
}


image.png


  1. 若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝我们叫做浅拷贝,或者值拷贝


class Date
{
public:
  Date(int year = 1900, int month = 1, int day = 1)
  {
    _year = year;
    _month = month;
    _day = day;
  }
private:
  int _year;
  int _month;
  int _day;
};
int main()
{
  Date d1;
  // 这里d2调用的默认拷贝构造完成拷贝,d2和d1的值也是一样的。
  Date d2(d1);
  return 0;
}


  1. 编译器生成的默认拷贝构造函数已经可以完成字节序的值拷贝了,对于像日期类这样的类(只有指针类型的类)是没必要的,编译器生成的足够使用了,而对于存在指针类型的成员函数则会存现问题


class String
{
public:
  String(const char* str = "xxxx")
  {
    _str = (char*)malloc(strlen(str) + 1);
    strcpy(_str, str);
  }
  ~String()//析构函数,进行释放动态开辟的空间
  {
    cout << "~String()" << endl;
    free(_str);
  }
private:
  char* _str;
};
int main()
{
  String s1("hello");
  String s2(s1);
}


  • 解释:


当两个同类对象的成员指针变量同时指向一个动态开辟的空间,如果一个对象对这空间进行释放,而另一个对象却依旧保存着该地址(野指针),如果进行操作该空间(再次free等)则会造成程序崩溃


image.png



相关文章
|
18小时前
|
C语言 C++
c++的学习之路:4、入门(3)
c++的学习之路:4、入门(3)
7 0
|
18小时前
|
编译器 C++
c++的学习之路:23、多态(2)
c++的学习之路:23、多态(2)
4 0
|
21小时前
|
Java C++
C++的学习之路:21、继承(2)
C++的学习之路:21、继承(2)
5 0
|
21小时前
|
存储 C++ 容器
c++的学习之路:14、list(1)
c++的学习之路:14、list(1)
8 0
|
21小时前
|
存储 算法 C语言
c++的学习之路:9、STL简介与string(1)
c++的学习之路:9、STL简介与string(1)
3 0
|
21小时前
|
C++
c++的学习之路:7、类和对象(3)
c++的学习之路:7、类和对象(3)
6 0
|
22小时前
|
存储 编译器 C语言
c++的学习之路:5、类和对象(1)
c++的学习之路:5、类和对象(1)
4 0
|
3天前
|
存储 安全 C语言
【C++】string类
【C++】string类
|
存储 编译器 Linux
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
标准库中的string类(中)+仅仅反转字母+字符串中的第一个唯一字符+字符串相加——“C++”“Leetcode每日一题”
|
5天前
|
编译器 C++
标准库中的string类(上)——“C++”
标准库中的string类(上)——“C++”

热门文章

最新文章