【C++的类与对象(下)】

这篇具有很好参考价值的文章主要介绍了【C++的类与对象(下)】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、细说构造函数

1.1初始化列表的引入

我们都知道构造函数的作用是在创建对象的时候给对象的成员属性赋值。
那么下面的场景可以用构造函数进行赋值吗?

#include<iostream>
using namespace std;
class example1
{
public:
	//可以这么写吗?  编译器能通过吗?
	example1(int i, int j)
	{
		x = i;
		j = y;
	}
private:
	const int x;
	int& y;
};
int main()
{
	return 0;
}

答案是不可以的。编译器也不支持这么胡搞。
【C++的类与对象(下)】
首先要知道为什么不可以这么写。
【C++的类与对象(下)】
为了解决上面不能使用构造函数来初始化的场景,所以就引入了初始化列表这个概念。可以通过初始化列表来完成初始化。比如:
【C++的类与对象(下)】

1.2初始化列表

初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
注:

  1. 每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
  2. 类中包含以下成员,必须放在初始化列表位置进行初始化:引用成员变量、 const成员变量、自定义类型成员(且该类没有默认构造函数时)
    怎么理解上面被加粗的这段话呢?
    之前在C++类和对象(上)说过默认构造函数会对内置类型不做处理对自定义类型会调用其默认构造函数。这句话准确的来讲是在初始化列表会调用自定义类型的默认构造函数。如图:
    【C++的类与对象(下)】
    那如果example2没有默认构造函数呢?我的意思是你重载了一个有参构造函数、或者说你重载了两个有参构造函数,此时默认构造函数就失效了,而编译器又不知道你调用的有参构造函数的参数是多少,所以编译器不能帮你调用有参构造函数,所以就会报错。
    【C++的类与对象(下)】
  3. 尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
  4. 成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关。这个比较坑,稍不留神都不知道自己错在哪里。比如:
    【C++的类与对象(下)】
    初始化列表顺序是从_arr开始,而_arr需要使用_capacity来初始化,慢慢的开始离谱了。

1.2关键字explicit

这个是4/6级词汇。顺带复习一下。
explicit:adj 清楚的、明确的、易于理解的。
explicitness:n 直言不讳、明确性
explicitly:adv 清楚明确地
在了解explicit这个关键字的作用之前先看看这个代码:
【C++的类与对象(下)】
这么写为什么不会报错呢?这个代码不符合我们对类的常规认识呀。
其实这里发生了隐式类型转换。具体如下:
【C++的类与对象(下)】
这里再补充一个奇葩的写法。如下:
【C++的类与对象(下)】
说明如下:
【C++的类与对象(下)】
那如果你不想发生隐式类型转换怎么办呢?就需要用到关键字explicit 这个英文含义是直接了当的,不需要隐式类型转换这个含糊不清的东西。比如:
【C++的类与对象(下)】

二、static成员

2.1static成员的特性

声明为static的类成员称为类的静态成员,用static修饰的成员变量,称之为静态成员变量;用static修饰的成员函数,称之为静态成员函数。静态成员变量一定要在类外进行初始化。
特点:

  1. 静态成员为所有类对象所共享,不属于某个具体的对象,存放在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字,类中只是声明
  3. 类静态成员即可用 类名::静态成员 或者 对象.静态成员 来访问
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员也是类的成员,受public、protected、private 访问限定符的限制

2.2题目:实现一个类,计算程序中创建出了多少个类对象

代码:

#include<iostream>
using namespace std;
class example
{
public:
	example()
	{
		num++;
	}
	static int GetNum()
	{
		return num;
	}
private:
	static int num;
};
int example::num = 0;
void test()
{
	for (int j = 0; j < 10; j++)
	{
		example ex;
	}
}
int main()
{
	for (int i = 0; i < 10; i++)
	{
		example ex;
	}
	test();
	cout << example::GetNum() << endl;
	return 0;
}

**补充:**非静态成员函数可以调用静态成员函数,而静态成员函数不可以调用非静态成员函数。
为什么呢?解释如下:
刚刚上面说过了静态成员函数不能访问非静态成员变量。如果一个非静态成员函数A进行了对非静态成员函数的访问,那么此时你用静态成员函数B再去访问非静态成员函数A不就相当于完成了对非静态成员的访问了?那么就矛盾了。

2.3题目:设计一个类 只能再栈上或者堆上创建

#include<iostream>
using namespace std;
class example
{
public:
	static example GetObjectInStack()
	{
		example ex;
		return ex;
	}
	static example* GetObjectInHeap()
	{
		return new example;
	}
private:
	example()
	{}
};
int main()
{
	example ex1 = example::GetObjectInStack();
	example* ex2 = example::GetObjectInHeap();
	return 0;
}

三、友元

友元提供了一种突破封装的方式,有时提供了便利。但是友元会增加耦合度,破坏了封装,所以友元不宜多用。(关于这个耦合度我自己也不怎么清楚,这里先给自己埋下一个坑,等以后自己的知识储备更加完善后来填坑,特此标注来提醒自己。)
友元分为:友元函数友元类

3.1友元函数

友元函数简单来讲呢就是:类外的函数想要访问类的属性需要成为该类的友元函数。
怎么成为该类的友元函数呢?
语法:在类内的任意位置中加上friend 函数返回值 函数名(函数参数);
比如:

#include<iostream>
using namespace std;
class Date
{
	friend void Printf();
public:
	Date(int year, int month, int day)
	{
		Year = year;
		Month = month;
		Day = day;
	}
private:
	int Year;
	int Month;
	int Day;
};
void Printf()
{
	Date d1(2023, 5, 16);
	cout << d1.Year << "-" << d1.Month << "-" << d1.Day << endl;
}
int main()
{
	Printf();
	Date d2(2022, 12, 12);
	return 0;
}

【C++的类与对象(下)】
说明:友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。

3.2友元类

友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
友元类的特性:

  1. 友元关系是单向的,不具有交换性。
    如果A类是B的友元类不能说明B类是A类的友元类。
  2. 友元关系不能传递
  3. 友元关系不能继承
    使用如下:
#include<iostream>
using namespace std;
class Time
{
	friend class Date;
public:
	Time(int hour, int minute, int second)
	{
		Hour = hour;
		Minute = minute;
		Second = second;
	}
private:
	int Hour;
	int Minute;
	int Second;
};
class Date
{
	friend void Printf(const Date& d1);
public:
	Date(int year, int month, int day)
	{
		Year = year;
		Month = month;
		Day = day;
	}
	void PrintAllDate(const Time& t)
	{
		cout << Year << "-" << Month << "-" << Day << "_" << t.Hour << ":" << t.Minute << ":" << t.Second << endl;
	}
private:
	int Year;
	int Month;
	int Day;
};
void Printf(const Date& d1)
{
	cout << d1.Year << "-" << d1.Month << "-" << d1.Day << endl;
}
int main()
{
	Date d1(2023, 5, 16);
	Printf(d1);
	Time t1(19, 44, 55);
	d1.PrintAllDate(t1);
	return 0;
}

【C++的类与对象(下)】

四、内部类

概念:如果一个类定义在另一个类的内部,这个内部类就叫做内部类。内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去访问内部类的成员。外部类对内部类没有任何优越的访问权限。
注意:内部类就是外部类的友元类,参见友元类的定义,内部类可以通过外部类的对象参数来访问外部类中的所有成员。但是外部类不是内部类的友元。
特性:

  1. 内部类可以定义在外部类的public、protected、private都是可以的。
  2. 注意内部类可以直接访问外部类中的static成员,不需要外部类的对象/类名。
  3. sizeof(外部类)=外部类,和内部类没有任何关系。
    比如:
#include<iostream>
using namespace std;
class External
{
public:
	class Internal
	{
	public:
		void fun1(const External& e1)
		{
			cout << "val1=:" << e1.val1 << "val2=:" << e1.val2 << endl;
			cout << x << endl;
		}
	};
private:
	static int x;
	int val1;
	int val2;
};
int External::x = 888;
int main()
{
	cout << sizeof(External) << endl;
	return 0;
}

【C++的类与对象(下)】

五、匿名对象

匿名对象与有名对象的定义如下:

#include<iostream>
using namespace std;
class Example
{
public:
	Example(int x, int y)
	{
		cout << "构造函数调用" << endl;
		val1 = x;
		val2 = y;
	}
	~Example()
	{
		cout << "析构函数的调用" << endl;
	}
	void func01()
	{
		cout << "func01成员函数调用" << endl;
	}
private:
	int val1;
	int val2;
};
int main()
{
	Example ex1(666, 888);//有名对象
	Example(888, 666);//匿名对象
	return 0;
}

他们从定义的形式来看差别在于匿名对象没有名字。
在生命周期来看,匿名对象的生命周期在当前行结束之前,出了当前行后就被销毁。如:
【C++的类与对象(下)】
匿名对象也是可以调用成员函数的。比如:
【C++的类与对象(下)】
匿名对象与临时变量一样具有常性。所以对象在引用一个临时变量前必须加上const。
【C++的类与对象(下)】
【C++的类与对象(下)】
加上const后事情开始变得有趣了。匿名对象的生命周期变长了,生命周期变得在当前函数的作用域内。因为不这样的话就变成野引用了。比如:
【C++的类与对象(下)】文章来源地址https://www.toymoban.com/news/detail-438121.html

到了这里,关于【C++的类与对象(下)】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C++ | 谈谈构造函数的初始化列表

    我们知道,对于下面这个类A的成员变量 _a1 和 _a2 属于【声明】,还没有在内存中为其开辟出一块空间以供存放,真正开出空间则是在【定义】的时候,那何时定义呢?也就是使用这个类A去实例化出对象的时候 这个对象的空间被开出来了,难道里面的成员变量就一定开出空间

    2023年04月11日
    浏览(97)
  • 【C++奇遇记】构造函数 | 初始化列表

    🎬 博客主页:博主链接 🎥 本文由 M malloc 原创,首发于 CSDN🙉 🎄 学习专栏推荐:LeetCode刷题集 数据库专栏 初阶数据结构 🏅 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正! 📆 未来很长,值得我们全力奔赴更美好的生活✨ 🐤本篇文章将讲授C++的初始化列表相关的知识

    2024年02月12日
    浏览(55)
  • C++中包含初始化列表的构造函数

    构造函数对初始化成员变化很有用。另一种初始化成员的方式是使用初始化列表。对于程序中接受两个参数的构造函数,其包含初始化列表的变种类似于下面这样: 格式为: :成员变量1(参数1),成员变量2(参数2) 编译器会将初始化列表一一转换成代码,并将这些代码放

    2024年02月05日
    浏览(53)
  • [C++]类与对象(下) -- 初始化列表 -- static成员 -- 友元 -- 内部类,一篇带你深度了解。

      目录 1、再谈构造函数 1.1 构造函数体赋值 1.2 初始化列表 1.2.1 初始化列表的意义 1.3 explicit 2、static成员 2.1 问题引入 2.2 特性 3、友元 3.1 友元函数 3.2 友元类 4、内部类 在创建对象时,编译器通过调用构造函数,给对象中各个成员变量一个合适的初始值。 我们构造函

    2024年02月12日
    浏览(44)
  • 【C++】构造函数和初始化列表的性能差距

    构造函数和初始化列表的性能差距对比测试 在C++类和对象中,你可能听到过更加推荐用初始化列表来初始化类内成员。如果类内成员是自定义类型,则只能在初始化列表中调用自定义类型的构造函数。 但初始化列表和在构造函数体内直接赋值有无性能差距呢?今天就用一份

    2024年02月11日
    浏览(42)
  • 【C++】类与对象(构造函数、析构函数、拷贝构造函数、常引用)

       🌈个人主页: 秦jh__https://blog.csdn.net/qinjh_?spm=1010.2135.3001.5343 🔥 系列专栏:   目录 类的6个默认成员函数 构造函数 特性  析构函数 特性  析构的顺序 拷贝构造函数 特性 常引用      💬 hello! 各位铁子们大家好哇。              今日更新了类与对象的构造函数、

    2024年02月21日
    浏览(42)
  • c++类和对象(拷贝构造、运算符重载、初始化列表、静态成员、友元等)

    拷贝构造函数的特征: 1、拷贝构造函数是构造函数的一个重载形式; 2、拷贝构造函数的参数只有一个且必须是同类类型对象的引用, 使用传值方式编译器直接报错 ,因为会引发无穷递归调用。 在c++中自定义类型 传值传参 的时候要调用拷贝构造函数。 3、若未显式定义,

    2024年02月15日
    浏览(36)
  • 【C++】const、static关键字和构造函数初始化

    💗个人主页💗 ⭐个人专栏——C++学习⭐ 💫点击关注🤩一起学习C语言💯💫 目录 1. const修饰成员函数 1.1 语法格式 1.2 权限放大缩小 1.3 思考 1.4 解答 2. 再谈构造函数 2.1 构造函数体赋值 2.2 初始化列表 2.3 explicit 3. static成员 3.1 静态变量 3.2 静态函数 3.3 静态成员变量

    2024年02月19日
    浏览(46)
  • C++ 学习 ::【基础篇:13】:C++ 类的基本成员函数:类类型成员的初始化与构造函数问题

    本系列 C++ 相关文章 仅为笔者学习笔记记录,用自己的理解记录学习!C++ 学习系列将分为三个阶段: 基础篇、STL 篇、高阶数据结构与算法篇 ,相关重点内容如下: 基础篇 : 类与对象 (涉及C++的三大特性等); STL 篇 : 学习使用 C++ 提供的 STL 相关库 ; 高阶数据结构与算

    2024年02月08日
    浏览(60)
  • Python的类与对象、构造方法、类与对象三大特性封装、继承和多态、类型注解

      使用对象组织数据 在程序中是可以做到和生活中那样,设计表格、生产表格、填写表格的组织形式的。 在程序中设计表格,我们称之为: 设计类(class) class Student: name None #记录学生姓名 在程序中打印生产表格,我们称之为: 创建对象 #基于类创建对象 stu_1 Student() stu_2 St

    2024年02月02日
    浏览(54)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包