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

目录
  • 初始化列表
    • 引论
    • 初始化列表
  • explicit关键字
    • 引论
    • explicit关键字使用
  • static成员
  • 友元
    • 引论
    • 友元
  • 内部类
    • 基础概念
    • 内部类的使用
  • 补充
    • 析构顺序例题
  • 总结

初始化列表

引论

//初始化列表的引出
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++推荐使用初始化列表进行初始化

什么是初始化列表?

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

:_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;
}

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

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

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

引用和const变量必须初始化

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

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

explicit关键字

引论

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

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

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

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

explicit关键字使用

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

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

static成员

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

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

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

一份内存,多对象使用

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

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

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

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

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

//调用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;
}

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

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

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

待了解:链接属性

友元

引论

友元

什么是友元?

友元是一种定义在类外部的普通函数或类,但它需要在类体内进行说明,为了与该类的成员函数加以区别,在说明时前面加以关键字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;
}

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

类的声明: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;
}

友元==突破类域

内部类

基础概念

什么是内部类?

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

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

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

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

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

内部类的使用

//内部类使用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++不咋用内部类,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++一般不怎么用,内部类理解为外部类的友元,同时受到访问限定符的限制,类外使用内部类得用::突破类域限制
  • 面向对象是在模拟是在抽象模拟我们的现实世界!

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

(0)

相关推荐

  • C++学习笔记之类与对象详解

    目录 前言: 1.访问限定符: [问题]C++中 struct和class的区别是什么? 2.封装 [问题]在类和对象的阶段,我们只研究类的封装特性,那什么是封装呢? 3.类的定义与声明 [问题]函数调用的问题 4.类的作用域 5.类的实例化 6.类的分类 总结 前言: 1.C 语言是面向过程的,关注的是过程,分析出求解的步骤,通过函数逐步调用解决问题. 2.C++是基于面向对象的,关注的是对象,蒋一件事情拆分成不同的对象,靠对象之间的交互完成. 举个例子:外卖系统 面向过程是下单.接单.送餐的

  • C++类和对象实战之Date类的实现方法

    目录 零.前言 一.Date类相关接口 二.具体接口函数实现 1.获取月份天数 2.Date打印 3.Date构造函数 4.Date析构函数 5.Date拷贝构造函数 6.Date赋值重载函数 7.Date+=天数 8.Date+天数 9.Date-=天数 10.Date-天数 11.++Date 12.Date++ 13.–Date 14.Date– 15.日期比较 16.Date相减 17.日期输入\日期输出 总结 零.前言 在学了C++类和对象基本知识以及六个默认成员函数后,我们可以上手实

  • C++初阶教程之类和对象

    目录 类和对象<上> 1. 类的定义 2. 类的封装 2.1 访问限定修饰符 2.2 类的封装 3. 类的使用 3.1 类的作用域 3.2 类的实例化 4. 类对象的存储 5. this 指针 5.1 this 指针的定义 5.2 this 指针的特性 类和对象<中> 1. 构造函数 1.2 构造函数的定义 2.2 构造函数的特性 2. 析构函数 2.1 析构函数的定义 3. 拷贝构函数 3.1 拷贝构造函数的定义 3.2 拷贝构造函数的特性 4. 运算符重载 4.1 运算符重载的

  • c++类和对象基本概念

    目录 什么是类? 什么是对象? 类的定义 创建对象 成员访问(初始化) 总结 什么是类? 一系列事物的抽象,对于c++而言,万事万物都可以是类. 类包括:属性+行为 属性:事物特征->数据类型描述: 行为事物的操作->函数描述: 什么是对象? 类的具体化,类的实例化,抽象->具象: 类的特点:封装.继承.派生.多态. 类的定义 创建方法:class class 类名{ //权限限定词 public: protected://保护属性 private://当不做继承时,数据成员写成私有属性

  • C++类和对象之多态详解

    目录 多态基本概念和原理剖析 多态案例1 计算器类 纯虚函数和抽象类 多态案例2 制作饮品 虚析构和纯虚析构 多态案例3 电脑组装 多态基本概念和原理剖析 多态:多态是C++面向对象的三大特性之一.多态分为静态多态和动态多态. 静态多态:函数重载和运算符重载属于静态多态,复用函数名. 动态多态:派生类和虚函数实现运行时多态. 区别: 静态多态的函数地址早绑定,编译阶段确定函数地址. 动态多态的函数地址晚绑定,运行阶段确定函数地址. #include <iostream> using names

  • C++类和对象之封装详解

    目录 封装的意义以及示例 访问权限 公共权限 public 保护权限 protected 私有权限 private struct 和 class的区别 成员属性私有化 案例1:设计立方体类 案例2:点和圆的关系 总结 封装的意义以及示例 封装是C++面向对象三大特征之一 封装的意义: 将属性和行为作为一个整体,表现生活中的事物将属性和行为加以权限控制 语法:class 类名{  访问权限 : 属性  /  行为 }: 类的对象的公共数据成员可以使用直接成员访问运算符 . 来访问. 示例1: 设计

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

    目录 初始化列表 引论 初始化列表 explicit关键字 引论 explicit关键字使用 static成员 友元 引论 友元 内部类 基础概念 内部类的使用 补充 析构顺序例题 总结 初始化列表 引论 //初始化列表的引出 class B { public: B() { cout << "我是B的构造函数" << endl; } private: int _b; }; class A { public: A() { cout << "我

  • 详解php中的类与对象(继承)

    简介 在php中,类型的继承使用extends关键字,而且最多只能继承一个父类,php不支持多继承. class MyClass { public $dat = 0; public function __construct($dat) { $this->dat = $dat; } public function getDat() { return "$this->dat\n"; } } class MySubClass extends MyClass { public fu

  • javaScript中定义类或对象的五种方式总结

    第一种方式: 工厂方法 能创建并返回特定类型的对象的工厂函数(factory function). function createCar(sColor){ var oTempCar = new Object; oTempCar.color = sColor; oTempCar.showColor = function (){ alert(this.color); }; return oTempCar; } var oCar1 = createCar(); var oCar2 = createCa

  • ES6中定义类和对象的方法示例

    本文实例讲述了ES6中定义类和对象的方法.分享给大家供大家参考,具体如下: 类的基本定义和生成实例: // 类的基本定义和生成实例 class Parent{ //定义一个类 constructor(name='xiaxaioxian'){ this.name= name; } } // 生成一个实例 let g_parent = new Parent(); console.log(g_parent); //{name: "xiaxaioxian"} let v_parent = ne

  • Java 中的类和对象详情

    目录 1.类的定义 2.类中变量的类型 3.构造方法 4.重载方法 5.继承 5.1 重写方法 6.创建对象 7.访问实例变量和方法 8.比较对象 8.1 使用 == 比较对象 8.2 使用 equals() 比较对象 类可以看成是创建Java对象的模板 1.类的定义 public class Dog { String name; int age; void eat() { } void sleep() { } } 2.类中变量的类型 局部变量:在方法或语句块中定义的变量被称为局部变量.变量声明

  • Python面向对象编程中的类和对象学习教程

    Python中一切都是对象.类提供了创建新类型对象的机制.这篇教程中,我们不谈类和面向对象的基本知识,而专注在更好地理解Python面向对象编程上.假设我们使用新风格的python类,它们继承自object父类. 定义类 class 语句可以定义一系列的属性.变量.方法,他们被该类的实例对象所共享.下面给出一个简单类定义: class Account(object): num_accounts = 0 def __init__(self, name, balance): self.name =

  • Python中的类与对象之描述符详解

    描述符(Descriptors)是Python语言中一个深奥但却重要的一部分.它们广泛应用于Python语言的内核,熟练掌握描述符将会为Python程序员的工具箱添加一个额外的技巧.为了给接下来对描述符的讨论做一些铺垫,我将描述一些程序员可能会在日常编程活动中遇到的场景,然后我将解释描述符是什么,以及它们如何为这些场景提供优雅的解决方案.在这篇总结中,我会使用新样式类来指代Python版本. 1.假设一个程序中,我们需要对一个对象属性执行严格的类型检查.然而,Python是一种动态语言,所以并不

  • JavaScript中的类数组对象介绍

    JavaScript中,数组是一个特殊的对象,其property名为正整数,且其length属性会随着数组成员的增减而发生变化,同时又从Array构造函数中继承了一些用于进行数组操作的方法.而对于一个普通的对象来说,如果它的所有property名均为正整数,同时也有相应的length属性,那么虽然该对象并不是由Array构造函数所创建的,它依然呈现出数组的行为,在这种情况下,这些对象被称为"类数组对象".以下是一个简单的类数组对象: 复制代码 代码如下: var o = {0:42,

  • 进一步深入Ruby中的类与对象概念

    Ruby是纯面向对象的语言,所有项目似乎要Ruby中为一个对象.Ruby中的每个值是一个对象,即使是最原始的东西:字符串,数字甚至true和false.即使是一个类本身是一个对象,它是Class类的一个实例.本章将通过所有功能涉及到Ruby的面向对象. 类是用来指定对象的形式,它结合了数据表示和方法操纵这些数据,转换成一个整齐的包.在一个类的数据和方法,被称为类的成员. Ruby类的定义: 定义一个类,定义的数据类型的草图. 这实际上并不定义任何数据,但它定义的类名字的意思什么,即是什么类的对象

  • C++类和对象实例解析(二)

    C++既是面向对象也是面向过程的语言,在这里就有一个重要的概念--类.         何谓类?类是对对象的一种抽象,举例来讲:每一个实实在在存在的人就是一个对象,人有很多共同的特征(一个头,两条腿,能走,能跑),这具有共同特征的人就成为一个类.类是一个抽象的名词,每一个人(即对象)是这个类的实例.         对象间具有的共同特征是对象的属性和行为.录像机是一个对象,它的属性是生产厂家.牌子.重量.颜色等等,它的行为就是它的功能,如录像.放像.快进.倒退等操作. C++程序中,需要先定义一

随机推荐