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

初始化列表、静态成员、友元

一:构造函数函数初始化列表初始化:
初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
类中包含以下成员,必须放在初始化列表位置进行初始化:

  1. 引用成员变量
  2. const成员变量
  3. 自定义类型成员(该类没有默认构造函数) 默认构造函数就是不用传参可以调用的构造函数有三个:1.全缺省 2.无参的 3.编译器自动生成的
class A
{
public:A(int x = 0) // 默认构造函数 定义Date d的时候可以调动_x = x;A(int x)  // 不是默认构造函数 定义Date d的时候调不动,得配合在Date类的初始化的初始化列表调用才可以调得动_x = x;
private:int _x;
}
class Date
{
public:Date(int year, int month, int day):_year(year),_month(month),_day(day),_n(10),_tmp(year),_a(1) //如果A中没有默认构造函数就需要这样子做{}
private:// 不是成员变量的定义,仅仅是成员变量的声名// 这些成员都属于对象,在main中对象被定义出来后才算定义了成员变量int _year;int _month;int _day;int& _tmp; //引用必须在定义的时候(初始化列表)初始化 (const也得在定义的时候初始化)const int _n; //必须在初始化列表初始化,不能在函数体内初始化A _a; //自定义类型定义的时候自动调用它的构造函数
};

成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
下述代码private中先定义的_a2,因此初始化先初始化a2,再初始化_a1,所以选D。1 随机值

class A
{
public:A(int a):_a1(a),_a2(_a1){}void Print() {cout<<_a1<<" "<<_a2<<endl;}
private:int _a2;int _a1;
}
int main() {A aa(1);aa.Print();
}

单参数的构造函数支持隐式类型转换。

class A
{
public:A(int a):_a(a){}
private:int _a;
};
class B
{
public:explicit A(int b) //加上这个关键字不支持类型转换:_b(b){}
private:int _b;
};
int main()
{	int i = 0;double j = i; // 隐式类型转换A a1 = 2; // 将int类型2转换为 A 类型 调用构造函数构造B b1 = 2; // 不能编译过去A(2); // 构造匿名对象 生命周期只在这一行
}

二:静态成员:
实现一个类,计算中程序中创建出了多少个类对象。
在类中定义静态成员,然后在构造和拷贝构造函数中对静态成员变量进行++,每调用一次就会自己++一次。类中的静态成员变量是声名,不在构造函数初始化,需要在类外进行初始化定义。
静态成员函数和普通的成员函数区别:没有this指针,不能访问非静态成员。

  1. 静态成员为所有类对象所共享,不属于某个具体的实例,它在静态区
  2. 静态成员变量必须在类外定义,定义时不添加static关键字
  3. 类静态成员即可用类名::静态成员或者对象.静态成员来访问 就是A()::GetN()、a1.GetN()、A::GetN()
  4. 静态成员函数没有隐藏的this指针,不能访问任何非静态成员
  5. 静态成员和类的普通成员一样,也有public、protected、private3种访问级别,也可以具有返回值

静态成员函数可以调用非静态成员函数吗?不可以 在GetN中不能调用f,因为GetN没有this指针
非静态成员函数可以调用类的静态成员函数吗?可以,f可以调用GetN。

class A
{
public:A(){_n++;}A(const A& a){_n++;}//int GetN()//{//	return _n;//}void f(){}// 静态成员函数和普通的成员函数区别:没有this指针,不能访问非静态成员。static int GetN(){}
private:// 声名 不在构造函数初始化static int _n; // 存在静态区 属于整个类 属于类的所有对象 生命周期是全局的
};
int A::_n = 0; // 在这里初始化 第一次可以初始化
int main()
{A a;cout << sizeof(A) << endl; // 1cout << sizeof(a) << endl; // 1cout << a.GetN() << endl; // 可以知道创建了多少次对象return 0;
}

题目:求1+2+3+…+n,要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句(A?B:C)。数据范围: 0<n≤200 进阶: 空间复杂度 O(1),时间复杂度 O(n)
解:创建一个Add类,n是多少就创建大小为n的Add类型的数组,这样在Add的构造函数定义++,对static类型的数据进行++,就可以完成求和。Init函数是为了防止在oj题目中多接口去测试而导致_i和_ret没有在下次调用初始化的问题。

class Add{
public:Add(){_ret += _i;_i++;}static int Get(){return _ret;}static void Init(){_i = 1;_ret = 0;}
private:static int _i;static int _ret;
};
int Add::_i = 1;
int Add::_ret = 0;
class Solution {
public:int Sum_Solution(int n) {Add::Init();Add arr[n]; //变长数组return Add::Get();}
};

题目:根据输入的日期,计算是这一年的第几天。保证年份为4位数且日期合法。
进阶:时间复杂度:O(n),空间复杂度:O(1)
输入描述:
输入一行,每行空格分割,分别是年,月,日
输出描述:
输出是这一年的第几天
eg:
输入:2012 12 31
输出:366

#include <iostream>
using namespace std;
int GetDay(int year, int month){int dayArray[13] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};int day = dayArray[month];// 每四年一润但百年不润 但是四百年润if (month == 2 &&((year % 4 == 0 && year % 100 != 0) || (year%400 == 0))){day += 1;}return day;
}
int main() {int _year = 0;int _month = 0;int _day = 0;int ret = 0;cin >> _year >> _month >> _day;while(_month > 0){_month--;ret += GetDay(_year, _month);}cout <<(ret + _day) << endl;
}

cout是ostream类型的对象
cin是istream类型的对象
友元函数:破坏封装的行为。
友元函数可以直接访问类的私有成员,它是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明,声明时需要加friend关键字。
友元函数可访问类的私有和保护成员,但不是类的成员函数
友元函数不能用const修饰 // const是修饰this指针的,友元函数不属于类函数。
友元函数可以在类定义的任何地方声明,不受类访问限定符限制,可以定义在类中任何位置
一个函数可以是多个类的友元函数
友元函数的调用与普通函数的调用和原理相同

class Date
{//友元函数的声名 加一个友元的函数声明。friend ostream& operator<<(ostream& _cout, const Date& d);friend istream& operator>>(istream& _cin, Date& d);
public:Date(int year, int month, int day): _year(year), _month(month), _day(day){}// cout << d1; cout就变成左操作数,就把cout给this了。ostream& operator<<(ostream& _cout) // ostream& operator<<(Date* this, ostream& _cout){_cout<<d._year<<"-"<<d._month<<"-"<<d._day;return _cout;}
prvate:int _year;int _month;int _day
};// 友元函数
ostream& operator<<(ostream& _cout, const Date& d) // ostream&的返回值可以支持连续输出
{_cout<<d._year<<"-"<<d._month<<"-"<<d._day;return _cout;
}
istream& operator>>(istream& _cin, Date& d) // 输入需要修改不加const
{_cin>>d._year>>"-">>d._month<<"-">>d._day;return _cin;
}
int main()
{Date d(2017, 12, 24);// cout<<d; // cout就变成左操作数,就把cout给this了,d<<cout; // 这个可以调用成员内函数打印 但写法不太相同 因此直接写成员函数不是很方便 cout << d; // 依靠友元通过类外函数访问成员内变量并打印Date d1(2017, 12, 24); // ostream&的返回值可以支持连续输出Date d2(2017, 12, 24);cout << d1 << d2; // 从左到右结合 cout<<d1返回一个coutreturn 0;
}

友元类: A是B的友元(在B中写friend class A;),A中可以访问B,B不能访问A。
友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员。
友元关系是单向的,不具有交换性。比如Time类和Date类,在Time类中声明Date类为其友元类,那么可以在Date类中直接访问Time类的私有成员变量,但想在Time类中访问Date类中私有的成员变量则不行。
友元关系不能传递,如果B是A的友元,C是B的友元,则不能说明C时A的友元。

class Date;   
// 前置声明
class Time
{friend class Date;  // Date要访问time的内容,把Date定义成time的友元类// 声明日期类为时间类的友元类,则在日期类中就直接访问Time类中的私有成员变量public:Time(int hour, int minute, int second): _hour(hour), _minute(minute), _second(second){}
private:int _hour;int _minute;int _second;
};
class Date // Date要访问time的内容,把Date定义成time的友元类
{
public:Date(int year = 1900, int month = 1, int day = 1): _year(year), _month(month), _day(day){}void SetTimeOfDate(int hour, int minute, int second){// 直接访问时间类私有的成员变量_t._hour = hour;_t._minute = minute;_t.second = second;}
private:int _year;int _month;int _day;Time _t;
};

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

相关文章:

  • comfyui实操:一个工作流让照片动起来!
  • 【CTF Web】Pikachu SSRF(curl) Writeup(SSRF+读取文件+探测端口)
  • 摸爬滚打半年,我是如何从小白进阶到渗透测试工程师
  • 将已有vs工程部分代码配置成cuda编译
  • Windows设置静态IP地址
  • 元创股份增利不增收:受政策影响较大,大客户沃得农机负作用不小
  • 智慧厂区车辆导航解决方案;智慧工厂电子地图应用解决方案;大型工厂内部导航解决方案;智慧工厂可视化地图应用方案
  • 【Next.js 项目实战系列】00-写在前面
  • python配合yolo分类模型开发分类软件
  • 影刀RPA实战:CSDN博文点赞收藏评论自动化工具
  • 5分钟了解软件开发的20项基本原则
  • PLM产品生命周期管理系统有哪家比较好?三品PLM系统:卓越的产品生命管理解决方案
  • 经纬恒润半主动悬架控制器成功量产
  • Vant 日期时间组件拓展
  • 网络IP地址冲突:含义、影响及应对策略‌
  • yarn error nopt@7.2.1: The engine “node“ is....Expected version “^14.17.0....
  • 【MySQL】VARCHAR和CHAR的区别?
  • PythonAI 学习大纲
  • 云原生介绍
  • 本地部署ComfyUI并添加强大的Flux.1开源文生图模型远程制作AI图片