C++面向对象程序设计之类与对象(1)

1. 类与对象 

    C++ 在 C 语言的基础上增加了面向对象编程,C++ 支持面向对象程序设计。类是 C++ 的核心特性,通常被称为用户定义的类型。

    类用于指定对象的形式,是一种用户自定义的数据类型,它是一种封装了数据和函数的组合。类中的数据称为成员变量,函数称为成员函数。类可以被看作是一种模板,可以用来创建具有相同属性和行为的多个对象。在C++中定义一个类要使用 class 关键字( class 默认为 private ,struct 默认为 public 

    下面我使用一段简单代码来阐述类与对象的关系:

#include<iostream>
using namespace std;

class Date
{
private:
	int _year;
	int _month;
	int _day;
};

int main()
{
	Date d1;
    Date d2;
	return 0;
}

 其中 class 是关键字,Date 是类名,private 下是三个成员变量,d1和d2是类的两个对象。 

2. 构造函数

在C语言中我们时常在一些零碎的小问题上要花费一点时间,比如初始化,所以在C++中为了方便程序员的编写,就有了构造函数,在程序运行时都会自动调用,并且构造函数是可以重载的。

构造函数通常和类名同名,在函数内部进行一些初始化,当然也可以设置缺省参数,时刻记住构造函数是可以重载的,所以根据需要可以定义多个构造函数。构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。 

构造函数有如下特性:

1. 函数名与类名相同。
2. 无返回值。
3. 对象实例化时编译器自动调用对应的构造函数。
4. 构造函数可以重载。

同样借助上面的同一段程序来解释:

#include<iostream>
using namespace std;

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		cout << "Date()" << endl;
		_year = year;
		_month = month;
		_day = day;
	}
    //成员函数
	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{

	Date d1(2024, 06, 13);
	d1.Print();

	return 0;
}

 一般地,我们可以在程序中设置一个全缺省的构造函数,这样可以方便很多。

3. 析构函数

     类的析构函数是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。

     析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。

     析构函数 : 与构造函数功能相反。析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作

析构函数的特性如下:

  1. 析构函数名是在类名前加上字符~。
  2. 无参数无返回值类型。 
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函          数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

代码如下:

#include<iostream>
using namespace std;

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		cout << "Date()" << endl;
		_year = year;
		_month = month;
		_day = day;
	}

	~Date()
    {
       cout << "~Date()" << endl;
		_year = 0;
		_month = 0;
		_day = 0;
    }

	void Print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{

	Date d1(2024, 06, 13);
	d1.Print();
	
	return 0;
}

但是上述的代码其实并不用析构函数,使用析构函数的程序一般符合下列特征:
1. 有资源需要显示清理(使用 malloc 或者 new了新的内存空间),就需要写析构。如: Stack(栈) List(链表)
2. 有两种场景不需要显示写析构,默认生成就可以了
     a、没有资源需要清理,如:Date
     b、内置类型成员没有资源需要清理。剩下都是自定义类型成员。如:MyQueue(一般就是成员变量本身就有析构函数,如Stack本来就有析构函数)

class MyQueue
{
private:
      Stack st1;
      Stack st2;
      int size =0;
};

4. 构造拷贝函数

    拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:
1. 通过使用另一个同类型的对象来初始化新创建的对象。
2. 复制对象把它作为参数传递给函数。
3. 复制对象,并从函数返回这个对象。
    如果在类中没有定义拷贝构造函数,编译器会自行定义一个。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。 

拷贝构造函数的特性:

1. 拷贝构造函数是构造函数的一个重载形式,

2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错因为引发无穷递归调用。

3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

一般的使用构造拷贝函数有如下规律:

1. 如果没有管理资源,一般情况不需要写拷贝构造,默认生成的拷贝构造就可以。如:Date
2. 如果都是自定义类型成员,内置类型成员没有指向资源,也类似默认生成的拷贝构造就可以。        如:MyQueue
3. 一般情况下,不需要显示写析构函数,就不需要写拷贝构造
4. 如果内部有指针或者一些值指向资源,需要显示写析构释放,通常就需要显示写构造完成深拷        贝。如:Stack(栈) Queue(队列) List(链表)等

实例代码如下:

#include<iostream>
using namespace std;

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		cout << "Date()" << endl;
		_year = year;
		_month = month;
		_day = day;
	}
	Date(const 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(2024, 06, 13);
	d1.Print();
	Date d2(d1);
	d2.Print();
	//同样是拷贝构造,更加常用
	Date d4 = d2;
	d4.Print();
	return 0;
}

相关推荐

  1. C++面向对象程序设计之类对象1

    2024-06-14 11:26:03       34 阅读
  2. C#面向对象程序设计

    2024-06-14 11:26:03       54 阅读
  3. 面向对象程序设计

    2024-06-14 11:26:03       33 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-14 11:26:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-14 11:26:03       100 阅读
  3. 在Django里面运行非项目文件

    2024-06-14 11:26:03       82 阅读
  4. Python语言-面向对象

    2024-06-14 11:26:03       91 阅读

热门阅读

  1. SQL 入门教程

    2024-06-14 11:26:03       33 阅读
  2. Go基础编程 - 07 - 字典(map)及其约束

    2024-06-14 11:26:03       34 阅读
  3. unity2d Ugui--Image城市道路汽车行驶

    2024-06-14 11:26:03       29 阅读
  4. vscode 调试

    2024-06-14 11:26:03       36 阅读
  5. 数据库中的数据分类

    2024-06-14 11:26:03       29 阅读
  6. LeetCode236.二叉树最近的公共祖先

    2024-06-14 11:26:03       51 阅读
  7. 利用API推动业务创新

    2024-06-14 11:26:03       25 阅读
  8. 从位运算看海象运算符

    2024-06-14 11:26:03       35 阅读
  9. Docker:使用Docker自动化部署项目

    2024-06-14 11:26:03       24 阅读
  10. Tomcat

    Tomcat

    2024-06-14 11:26:03      28 阅读