当前位置: 首页 > news >正文

[C++] C++类和对象 类的初始化列表和静态成员 类型转换/友元/内部类/匿名对象/编译器优化

目录

构造函数

1.1 构造函数赋值

1.2 初始化列表

1.3 explicit 关键字

2.类的静态成员

2.1 静态成员函数

2.2 静态成员变量

4.友元

4.1.友元函数

4.2.友元类

5. 内部类

5.1 内部类的概念及特性


构造函数

1.1 构造函数赋值

构造函数是在对象创建时由编译器自动调用为成员变量赋一个初值,你不写编译器默认生成,全缺省的构造函数也是默认构造

当然除了这种方式初始化,还可以通过初始化列表进行初始化

1.2 初始化列表

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

class Date
{
public://初始化列表初始化Date(int year = 1, int month = 1, int day = 1):_year(year),_month(month),_day(day){	}private://成员变量声明int _year;int _month;int _day;
};int main()
{//创建对象Date d1(2022, 5, 22);Date d2;return 0;}

在构造函数中,由编译器在对象创建时自动去初始化列表处完成成员变量的初始化,在对象的生命周期内,初始化列表有且只会进行一次初始化

const类型成员/引用类型成员/没有默认构造的自定义类型的成员,这三类成员必须走初始化列表初始化

对于成员变量,最后都会去初始化列表处初始化

例如,你在成员变量声明时给上缺省值,实际上编译器是在初始化列表处用你给的缺省值去进行初始化

语法:

        类名 ()

        :成员变量(表达式)

        ,成员变量(表达式) { }

class A

{

        A(int a = 0, int b = 0)

        :_a(a)        //以 :开始

        ,_b(b)        //以 , 做分割符

                          //成员变量(),括号内可以是表达式和变量

private:

        int _a = 1;        //C++11

        int _b = 1;        //C++11

};

上面可以看到,在变量声明处和参数列表处都给了缺省值,注意这里的缺省值是不同的

成员变量声明处给的缺省值(C++11支持的)

在你不实现构造函数,编译器调用默认生成的构造函数时,本来是对于内置类型不做处理的,这时候你用了缺省值,编译器就会用你给的这个缺省值初始化 

而参数列表的缺省值,你不去用,对成员变量不会有任何改变

const成员/引用成员/没有默认构造的自定义类型成员为什么要在初始化列表初始?

const成员:        

const成员定义后具有常性,需要赋初值,而编译器对内置类型默认不做处理

引用类型成员:        

引用类型成员在定义时必须指定引用的对象,且不可改变引用的对象,同样的编译器对内置类型默认不做处理

没有默认构造的自定义类型成员:

对于自定义类型,编译器去调它的默认构造函数,如果没有默认构造,就需要你去显示的调用构造

1.3 explicit 关键字

构造函数不仅可以构造与初始化对象,对于单个参数的构造函数,还具有类型转换的作用

class Date
{
public:Date(int year):_year(year){cout << "Date(int year)" << endl;}Date(const Date& d){cout << "Date(const Date& d)" << endl;}private:int _year;
};int main()
{Date d1(2022);//构造Date d2 = 2022;//构造+拷贝构造 ->优化return 0;
}

这里的2022是int类型,而d2是Date类型,此时就会发生类型转换,会创建一个Date的临时对象用这个int值2022去构造,想避免类型转换发生在函数前加上explicit关键字就可以禁止构造函数进行隐式类型转换 

class Date
{
public:explicit Date(int year) :_year(year){cout << "Date(int year)" << endl;}Date(const Date& d){cout << "Date(const Date& d)" << endl;}private:int _year;
};int main()
{Date d1(2022);//构造Date d2 = 2022;//构造+拷贝构造 ->优化return 0;
}

 

使用这种隐式类型转换的代码可读性不是很好,使用explicit可以禁止单参数构造函数进行隐式类型转换

2.类的静态成员

类的静态成员:

静态成员被所有类对象成员共享,不属于某个具体的实例

静态成员和类的普通成员一样,也有 public、protected、private三种访问级别

类静态成员想访问其他静态成员可以通过类名::静态成员或对象.静态成员访问

静态成员函数没有隐含的this指针,不能访问非静态成员

静态成员变量在类中只是声明,必须在类外进行定义,定义时不加static关键字

2.1 静态成员函数

class A 

{

public:

        static void func()

        {

                //.........

        }

private:
}

因为静态成员不是任何一个对象的,而是属于类的,在对象被实例化前就已经存在。这意味着无论创建多少个类的对象,静态成员都只有一份,被类创建的所有对象共享。

而隐含的this指针则是指向某一个类类型对象,而静态成员处于类本身,所以静态成员没有this指针

2.2 静态成员变量

静态成员变量存储在静态区,被所有的类对象共享,属于整个类。必须在类外进行定义

#include <iostream>
using namespace std;class Date
{
public:static int _count;Date(int year):_year(year){cout << "Date(int year)" << endl;}private:int _year;
};
//静态成员变量在类外定义指定类域
int Date::_count = 10;int main()
{Date d1(2022);cout << d1._count << endl;return 0;
}

4.友元

友元分为友元函数和友元类

友元提供了一种突破封装的方法,有时提供了便利,但这会增加代码之间的耦合度,破坏了封装,所以友元不宜多用

4.1.友元函数

友元函数定义在类外,它可以直接访问类的所有成员,不受访问限定符限制,在函数名前加上friend关键字

class Date
{
public:friend void PrintDate(const Date& d);
private:int _year = 1;int _month = 1;int _day = 1;
};void PrintDate(const Date& d)
{cout << d._year << "/" << d._month << "/" << d._day << endl;
}int main()
{Date d1;PrintDate(d1);return 0;
}

友元函数的说明

  • 友元函数不是类的成员,但可以访问类的所有成员
  • 友元函数可以在类中任意地方声明,不受类的访问限定符限制
  • 友元函数不可以加上const修饰
  • 一个函数可以时多个类的友元
  • 友元函数的调用和普通函数相同

4.2.友元类

友元类的所有成员函数都是另一个类的友元函数,都可以访问另一个类的所有成员

class Date
{
public:friend class Print;
private:int _year = 1;int _month = 1;int _day = 1;
};class Print
{
public:void PrintDate(const Date& d){cout << d._year << "/" << d._month << "/" << d._day << endl;}
};int main()
{Date d1;Print p;p.PrintDate(d1);return 0;
}

需要注意的是:

1.友元关系是单向的

比如Print类是Date类的友元,可以访问Date的所有成员,但Date类不是Print的友元,无法访问Print的私有和保护成员

2.友元关系不能传递

比如B是A的友元,C是B的友元,这不能说明C是A的友元

5. 内部类

5.1 内部类的概念及特性

内部类的概念:

内部类说白了就是在一个类里面再去定义一个类。所以如果一个类定义在另一个类的内部,这个内部类就叫做内部类。注意此时这个内部类是一个独立的类,它不属于外部类,更不能通过外部类的对象去调用内部类。外部类对内部类没有任何优越的访问权限

内部类天生就是外部类的友元

内部类就是外部类的友元类。注意友元类的定义,内部类可以通过外部类的对象参数来访问外部类中 的所有成员。但是外部类不是内部类的友元

内部类的特性:

特性:

1. 内部类可以定义在外部类的 public 、 protected 、 private 都是可以的
2. 注意内部类可以直接访问外部类中的 static 、枚举成员,不需要外部类的对象 / 类名
3. sizeof( 外部类 )= 外部类,和内部类没有任何关系


http://www.mrgr.cn/news/54062.html

相关文章:

  • Windows下部署autMan
  • 保研推荐信模板
  • C/C++ 每日一练:单链表的反转
  • Android应用性能优化的方法
  • 【数据结构与算法】之单链表反转
  • Spring Boot 接口数据加解密
  • Symbol简单介绍
  • 【电子通识】案例:两个按键同时按下把boot拉低电路如何设计?
  • VIT:论文关键点解读与常见疑问
  • mac安装jdk8
  • Linux——应用软件的生命周期
  • 0x3D service
  • 监督学习、无监督学习、半监督学习、强化学习、迁移学习、集成学习分别是什么对应什么应用场景
  • ReLitLRM: Generative Relightable Radiance for Large Reconstruction Models 论文解读
  • 二叉树刷题(JAVA)
  • NeRF三维重建—神经辐射场Neural Radiance Field(二)体渲染相关
  • Lua变量
  • 深⼊理解指针(2)
  • 进程间关系与守护进程
  • 【ELK】初始阶段
  • 2024年AI 制作PPT新宠儿,3款神器集锦,让你的演示与众不同
  • excel导出图片黑线简谈
  • 第一年改考408的学校有炸过的吗?怎么应对突然改考408?
  • URP学习四
  • 《Linux服务与安全管理》| 磁盘与文件系统管理
  • 《中安未来护照阅读器》