服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C++中的类与对象深度解析

C++中的类与对象深度解析

2022-09-16 14:07你算哪一个bug? C/C++

这篇文章主要为大家详细介绍了C++中的类与对象,使用数据库,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

初始化列表

//初始化列表的引出
class B
{
public:
	B()
	{
		cout << "我是B的构造函数" << endl;
	}
private:
	int _b;
};
class A
{
public:
	A()
	{
		cout << "我是A的构造函数" << endl;
	}
private:
	int _a;
	B b;
};
int main()
{
	A a;
	return 0;
}

C++中的类与对象深度解析

汇编验证:

C++中的类与对象深度解析

初始化列表

c++推荐使用初始化列表进行初始化

什么是初始化列表?

一个冒号开始,以逗号分隔的数据成员列表,每个成员变量后面放一个括号,括号中放初始值或者表达式

:_a(1)

,_aa(2)

这个就是初始化列表

//初始化列表使用demo
class A
{
public:
	A()
		:_a(1)//初始化列表
		, _aa(2)
	{
		cout << _a << " " << _aa << endl;
	}
private:
	int _a;
	int _aa;
};
int main()
{
	A a;
	return 0;
}

C++中的类与对象深度解析

  • 存在自定义型时,初始化列表,不写也认为有

只是认为啊,不写初始化列表会在函数体之前调用自定义类型的构造函数,写了初始化列表是会进入函数体(花括号)然后调用,具体的可以观察汇编

  • 成员变量只能在初始化列表里出现一次
  • 成员变量包含引用和const变量时,必须在初始化列表里初始化

引用和const变量必须初始化

  • 成员变量的声明次序就是初始化顺序,与在初始化列表里先后顺序无关

C++中的类与对象深度解析

初始化列表是推荐使用的,如果初始化列表不能解决问题,混着用(在构造函数体内初始化)就行了

 

explicit关键字

引论

//int赋给对象demo
class A
{
public:
	A(int){}
};
int main()
{
	A a = 1;
	return 0;
}

C++中的类与对象深度解析

这么写是合法的,赋值的过程发生了隐式类型转换,前提是必须有A(int这样的构造函数)

//多个int赋给对象demo
class A
{
public:
	A(int,int){}
};
int main()
{
	A a = {1,2};
	return 0;
}

C++中的类与对象深度解析

C++11支持多参数转换,C++98不支持

explicit关键字使用

前面提到,int可以赋给对象是隐式类型转换,如果要禁止这种用法,则用explicit修饰对应的构造函数

//explicit使用demo
class A
{
public:
	explicit A(int){}
};
int main()
{
	A a = 1;//error
	return 0;
}

C++中的类与对象深度解析

 

static成员

静态成员变量:static修饰的成员变量

静态成员函数:static修饰的成员函数

静态成员变量不是单单属于某一个对象的,一个类创建的多个对象使用这个静态成员变量时使用的也是同一块内存,即所有对象共有该静态成员变量

一份内存,多对象使用

静态成员函数一般用来访问静态成员,没有this指针

由于没有this指针,所以无法访问非静态的成员

计算类的大小时不包括静态成员

C++中的类与对象深度解析

计算类的大小可以认为是计算对象的大小,因为每个对象共有静态成员变量,所以不能认为该变量特定属于某一个对象

调用静态成员函数,初始化静态成员变量

//调用static函数和初始化static变量的democlass A{public:static int Print(){cout << "static int Print()" << endl;return _aa;}private:int _a;static int _aa;};int A::_aa = 1;int main(){A::Print();return 0;}//调用static函数和初始化static变量的demo
class A
{
public:
	static int Print()
	{
		cout << "static int Print()" << endl;
		return _aa;
	}
private:
	int _a;
	static int _aa;
};
int A::_aa = 1;
int main()
{
	A::Print();
	return 0;
}

C++中的类与对象深度解析

静态成员变量不能给缺省值,必须在类外初始化,因为在类外初始化时才分配空间,所以不在类外初始化就不能用,用了可能会导致链接错误

静态成员函数不能调用非静态成员函数,非静态成员函数可以调用静态成员函数

普通静态函数需要通过this指针调用,而静态成员函数没有this指针–百度

待了解:链接属性

 

友元

引论

C++中的类与对象深度解析

友元

什么是友元?

友元是一种定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字friend。–百度百科

友元的作用

突破封装

class Date
{
	friend bool operator==(Date d1, Date d2);

private:
	int _year;
	int _month;
	int _day;
};
bool operator==(Date d1,Date d2)
{
	return d1._year == d2._year
		&& d1._month == d2._month
		&& d1._day == d2._day;
}
int main()
{
	return 0;
}

C++中的类与对象深度解析

随笔记录:编译器找一些声明只会往上找

类的声明:class A;

如果我们在一个类内想访问另一个类的私有成员,就需要友元类

class Time
{
public:
	void GetData()
	{
		cout << d._year << d._month << d._day << endl;
	}
private:
	Date d;//借助这个对象
};
class Date
{
	friend class Time;
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	return 0;
}

C++中的类与对象深度解析

友元==突破类域

 

内部类

基础概念

什么是内部类?

类里面定义一个类,这就叫内部类

内部类就是外部类的友元类,所以内部类可以访问外部类的成员,用法也和友元类很像

计算类的大小时不算内部类

内部类内可以直接访问外部类的静态成员,不需要通过类名

内部类受到类域影响和访问限定符限制

内部类的使用

//内部类使用demo
class A
{
public:
	class B
	{
	public:
		B(const A& a)
		{
			cout << "我是内部类B" << endl;
			cout << "我可以访问外部类A的变量_a:" <<a._a << endl;
		}
	private:
		int _b;
	};
	A(){}
	A(const B& b)
	{
		cout << b._b << endl;//error
	}
private:
	int _a=1;
};
int main()
{
	A a;
	A::B b(a);
	return 0;
}	

C++中的类与对象深度解析

其实C++不咋用内部类,Java喜欢用内部类

 

补充

析构顺序例题

类A、B、C、D,问下面程序中析构函数的调用顺序?

C c;
int main()
{
	A a;
	B b;
	static D d;
	return 0;
}

答案:析构顺序 B A D C

构造顺序:C A B D

析构顺序是D B C A吗?不是

  • 析构函数的调用时期:对象声明周期结束后
  • 静态的变量存储在全局区,main函数结束后会销毁栈帧

①因为a,b都是局部对象,先构造则后析构,构造时是AB,则析构肯定是BA

换个角度理解,栈的特点是先进后出,那a先入栈就应该后销毁,所以b先调用析构函数

②剩下C D,C是全局对象,D是静态局部对象,这两个谁先析构?

静态局部变量先析构,全局变量C再析构

D先析构,C后析构,即DC

全局对象和静态局部对象的释放优先级在网上没有找到很好的解释

个人理解:CD都存在全局区,所以CD的构造顺序和析构顺序应该是相反的,即构造是CD,则析构是DC

组合①②,得到BADC

这种题的技巧:把局部变量作为一组,把全局和静态变量作为一组,写出两个相应的构造顺序,再逆置一下就得到相应的析构顺序,又因为局部变量先析构,再拼接两组的析构顺序得到答案

可以把上面那段代码拷到编译器上,然后自己写代码验证答案

 

总结

  • 初始化列表提供了一种更好的初始化的方式,如果初始化列表不能单独完成任务,就结合构造函数体完成初始化任务
  • explicit可以禁止内置类型和自定义类型的转换,具体操作就是修饰对应的构造函数
  • static成员可以牵扯出很多东西,比如静态成员函数可不可以非静态变量等等,抓住关键点:静态成员函数没有this指针,static成员变量始终是一块内存,类外初始化才会分配空间
  • 友元主要解决了我们在类外不能访问私有成员变量的问题,本质上破坏了封装,不建议大量使用
  • 内部类,C++一般不怎么用,内部类理解为外部类的友元,同时受到访问限定符的限制,类外使用内部类得用::突破类域限制
  • 面向对象是在模拟是在抽象模拟我们的现实世界!

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容!

原文链接:https://blog.csdn.net/m0_53005929/article/details/122781197

延伸 · 阅读

精彩推荐
  • C/C++C++中const、volatile、mutable使用方法小结

    C++中const、volatile、mutable使用方法小结

    这篇文章主要介绍了C++中const、volatile、mutable使用方法小结,需要的朋友可以参考下...

    Dawn_sf12152021-08-12
  • C/C++详解C++ new-handler机制

    详解C++ new-handler机制

    这篇文章主要介绍了C++ new-handler机制的相关资料,帮助大家更好的理解和使用c++,感兴趣的朋友可以了解下...

    Mr-xxx9392021-10-06
  • C/C++构造函数不能声明为虚函数的原因及分析

    构造函数不能声明为虚函数的原因及分析

    构造函数不需要是虚函数,也不允许是虚函数,因为创建一个对象时我们总是要明确指定对象的类型,尽管我们可能通过实验室的基类的指针或引用去访问...

    C语言教程网5502021-01-05
  • C/C++C++实现LeetCode(112.二叉树的路径和)

    C++实现LeetCode(112.二叉树的路径和)

    这篇文章主要介绍了C++实现LeetCode(112.二叉树的路径和),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下...

    Grandyang7692021-11-26
  • C/C++C++ 中滚动条的滚动问题

    C++ 中滚动条的滚动问题

    本文主要通过一个示例,给大家介绍了C++中滚动条的滚动问题,以及相关参数的解释,非常的详细,有需要的小伙伴可以参考下。...

    C++教程网7582021-02-28
  • C/C++C++实现神经网络框架SimpleNN的详细过程

    C++实现神经网络框架SimpleNN的详细过程

    本来自己想到用C++实现神经网络主要是想强化一下编码能力并入门深度学习,对C++实现神经网络框架SimpleNN的详细过程感兴趣的朋友一起看看吧...

    Peiy_Liu3512021-12-22
  • C/C++详解C语言的exp()函数和ldexp()函数以及frexp()函数

    详解C语言的exp()函数和ldexp()函数以及frexp()函数

    这篇文章主要介绍了详解C语言的exp()函数和ldexp()函数以及frexp()函数,注意这三个函数虽然看起来相似但实际功能却大相径庭!需要的朋友可以参考下...

    C语言教程网6262021-03-08
  • C/C++C++11关于auto关键字的使用示例

    C++11关于auto关键字的使用示例

    今天小编就为大家分享一篇关于C++11关于auto关键字的使用示例,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编...

    蜗牛2015722021-07-15