C++练级之路——类和对象(中)

简介: C++练级之路——类和对象(中)

1、六个默认成员函数

       我们创建一个类,如果我们什么都不写,类会自动生成六个默认成员函数;


接下来一个一个了解;

2、构造函数


       构造函数是一个特殊的函数,函数名和类名相同,主要是对类的初始化;


class Date
{
public:
  // 1.无参构造函数
  Date()
  {
    
  }
  // 2.带参构造函数
  Date(int year, int month, int day)
  {
    _year = year;
    _month = month;
    _day = day;
  }
  void Print()
  {
    cout << _year << "--" << _month << "--" << _day << endl;
  }
private:
  int _year;
  int _month;
  int _day;
};


构造函数的特性:


1.函数名和类名相同,无返回值,构造函数可以重载;

2.构造函数分为无参构造和有参构造;

3.有参构造还可以用缺省值;


例如:

//3.带缺省值的有参构造
Date(int year=2024, int month=4, int day=10)
{
  _year = year;
  _month = month;
  _day = day;
}


4.无参构造和全缺省构造不能同时调用,会报错,编译器会不知道该调用哪个;

5.如果没有写构造函数,编译器会自动生成一个构造函数,


注意:C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在

类中声明时可以给默认值。

例如:

private:
  int _year=1;
  int _month=1;
  int _day=1;


总结:

1、一般情况下构造函数需要我们自己去写;

2、只有少数情况下可以让编译器自动生成构造函数,类似MyQueue,成员全是自定义类型;

class stack
{
  //
};
class MyQueue
{
private:
  stack _st1;
  stack _st2;
};


3、析构函数


析构函数在类结束后清理调用的资源;

特性:

1.析构函数名是在类名前加上字符‘~';

2.无参数,无返回值;

3.一个类只有一个析构函数,若没有显式定义,编译器自动生成析构函数,析构函数不能重载;

4.对象生命周期结束后,编译器自动调用析构函数;

5.当类中没有申请资源时,可以不写析构函数,例如Date类,有资源申请时一定要写,否则会造成资源泄露,如stack;


4、拷贝构造


拷贝构造函数:只有一个形参;

特性:

1.拷贝函数也是构造函数的重载,

2.拷贝构造函数参数只能有一个,必须是类类型对象的引用,如果直接传类,编译器会报错,会引发无穷递归;

3.如果没有显式定义,编译器会自动生成默认的拷贝函数,默认的拷贝函数是浅拷贝或者值拷贝,就是不额外开辟空间,遇到一些需要额外开辟空间的类就不适用了;

class Date
{
public:
  //有参构造函数
  Date(int year=2024, int month=4, int day=11)
  {
    _year = year;
    _month = month;
    _day = day;
  }
  //拷贝构造函数
    //d是d1的引用
  Date(Date& d)
  {
    _year = d._year;
    _month = d._month;
    _day = d._day;
  }
  void Print()
  {
    cout << _year << "-" << _month << "-" << _day << endl;
  }
 
private:
  int _year;
  int _month;
  int _day;
};
 
int main()
{
  Date d1;
  d1.Print();
  Date d2 = d1;
  d2.Print();
 
  return 0;
}


注意:

类中如果没有涉及资源申请,可以不写拷贝构造函数,一旦涉及到资源申请,拷贝函数就是要写的,否则就是浅拷贝;

例如:

typedef int DataType;
 
class Stack
{
public:
  Stack(size_t capacity = 3)
  {
    cout << "Stack(size_t capacity = 3)" << endl;
 
    _array = (DataType*)malloc(sizeof(DataType) * capacity);
    if (NULL == _array)
    {
      perror("malloc申请空间失败!!!");
      return;
    }
    _capacity = capacity;
    _size = 0;
  }
 
  void Push(DataType data)
  {
    // CheckCapacity();
    _array[_size] = data;
    _size++;
  }
 
  void Print()
  {
    for (int i = 0; i < _size; i++)
    {
      cout << _array[i] << " ";
    }
    cout << endl;
  }
  // 其他方法...
  ~Stack()
  {
    cout << "~Stack()" << endl;
 
    if (_array)
    {
      free(_array);
      _array = NULL;
      _capacity = 0;
      _size = 0;
    }
  }
private:
  DataType* _array;
  int _capacity;
  int _size;
};
int main()
{
  Stack d1;
  d1.Push(1);
  d1.Push(2);
  d1.Push(3);
  d1.Print();
  Stack d2 = d1;
  d2.Print();
  return 0;
}


该程序会发生崩溃,因为没有写拷贝构造函数,编译器默认的拷贝构造是浅拷贝,导致d1和d2指向同一块空间,调用两次析构函数析构同一块空间,程序崩溃;

相关文章
|
11天前
|
设计模式 安全 编译器
【C++11】特殊类设计
【C++11】特殊类设计
30 10
|
16天前
|
C++
C++友元函数和友元类的使用
C++中的友元(friend)是一种机制,允许类或函数访问其他类的私有成员,以实现数据共享或特殊功能。友元分为两类:类友元和函数友元。类友元允许一个类访问另一个类的私有数据,而函数友元是非成员函数,可以直接访问类的私有成员。虽然提供了便利,但友元破坏了封装性,应谨慎使用。
44 9
|
11天前
|
存储 编译器 C语言
【C++基础 】类和对象(上)
【C++基础 】类和对象(上)
|
19天前
|
编译器 C++
【C++】string类的使用④(字符串操作String operations )
这篇博客探讨了C++ STL中`std::string`的几个关键操作,如`c_str()`和`data()`,它们分别返回指向字符串的const char*指针,前者保证以&#39;\0&#39;结尾,后者不保证。`get_allocator()`返回内存分配器,通常不直接使用。`copy()`函数用于将字符串部分复制到字符数组,不添加&#39;\0&#39;。`find()`和`rfind()`用于向前和向后搜索子串或字符。`npos`是string类中的一个常量,表示找不到匹配项时的返回值。博客通过实例展示了这些函数的用法。
|
19天前
|
存储 C++
【C++】string类的使用③(非成员函数重载Non-member function overloads)
这篇文章探讨了C++中`std::string`的`replace`和`swap`函数以及非成员函数重载。`replace`提供了多种方式替换字符串中的部分内容,包括使用字符串、子串、字符、字符数组和填充字符。`swap`函数用于交换两个`string`对象的内容,成员函数版本效率更高。非成员函数重载包括`operator+`实现字符串连接,关系运算符(如`==`, `&lt;`等)用于比较字符串,以及`swap`非成员函数。此外,还介绍了`getline`函数,用于按指定分隔符从输入流中读取字符串。文章强调了非成员函数在特定情况下的作用,并给出了多个示例代码。
|
19天前
|
C++
【C++】string类的使用④(常量成员Member constants)
C++ `std::string` 的 `find_first_of`, `find_last_of`, `find_first_not_of`, `find_last_not_of` 函数分别用于从不同方向查找目标字符或子串。它们都返回匹配位置,未找到则返回 `npos`。`substr` 用于提取子字符串,`compare` 则提供更灵活的字符串比较。`npos` 是一个表示最大值的常量,用于标记未找到匹配的情况。示例代码展示了这些函数的实际应用,如替换元音、分割路径、查找非字母字符等。
|
19天前
|
C++
C++】string类的使用③(修改器Modifiers)
这篇博客探讨了C++ STL中`string`类的修改器和非成员函数重载。文章介绍了`operator+=`用于在字符串末尾追加内容,并展示了不同重载形式。`append`函数提供了更多追加选项,包括子串、字符数组、单个字符等。`push_back`和`pop_back`分别用于在末尾添加和移除一个字符。`assign`用于替换字符串内容,而`insert`允许在任意位置插入字符串或字符。最后,`erase`函数用于删除字符串中的部分内容。每个函数都配以代码示例和说明。
|
19天前
|
安全 编译器 C++
【C++】string类的使用②(元素获取Element access)
```markdown 探索C++ `string`方法:`clear()`保持容量不变使字符串变空;`empty()`检查长度是否为0;C++11的`shrink_to_fit()`尝试减少容量。`operator[]`和`at()`安全访问元素,越界时`at()`抛异常。`back()`和`front()`分别访问首尾元素。了解这些,轻松操作字符串!💡 ```
|
24天前
|
C++
【C++】日期类Date(详解)②
- `-=`通过复用`+=`实现,`Date operator-(int day)`则通过创建副本并调用`-=`。 - 前置`++`和后置`++`同样使用重载,类似地,前置`--`和后置`--`也复用了`+=`和`-=1`。 - 比较运算符重载如`&gt;`, `==`, `&lt;`, `&lt;=`, `!=`,通常只需实现两个,其他可通过复合逻辑得出。 - `Date`减`Date`返回天数,通过迭代较小日期直到与较大日期相等,记录步数和符号。 ``` 这是236个字符的摘要,符合240字符以内的要求,涵盖了日期类中运算符重载的主要实现。
|
19天前
|
存储 编译器 Linux
【C++】string类的使用②(容量接口Capacity )
这篇博客探讨了C++ STL中string的容量接口和元素访问方法。`size()`和`length()`函数等价,返回字符串的长度;`capacity()`提供已分配的字节数,可能大于长度;`max_size()`给出理论最大长度;`reserve()`预分配空间,不改变内容;`resize()`改变字符串长度,可指定填充字符。这些接口用于优化内存管理和适应字符串操作需求。