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

全面理解类和对象(下)

文章目录

  • 再谈构造函数
    • 初始化列表
  • static
    • 概念:
  • 友元
    • 友元函数
    • 友元类
  • 内部类
  • 再次理解类和对象

再谈构造函数

class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};

上述代码有了初始值,但是不是初始化,因为初始化是一次性的,而构造函数可以多次赋值

初始化列表

🚩初始化列表:以一个 : 开始,接着以 ,分隔数据列表,每个对象后面接包含初始值的括号

class Date
{
public:Date(int year, int month, int day):_year(year),_month(month),_day(day){}
private:int _year;int _month;int _day;
};

1,成员对象在初始化列表只能出现一次
2,类中包含以下情况必须用初始化列表初始化

1,const 修饰
2, 引用
3,自定义类型(无默认构造函数的)

class A
{
public:A(int a):_a(a){ }
private:int _a;
};
class B
{
public:B(int b, int ret,int obj):_b(b), _ret(ret), _obj(obj){}
private:const int _b;int& _ret;A _obj;
};

🚩 3,尽量使用列表初始化,因为无论是否使用列表初始化,自定义类型都会先进行列表初始化。
🚩 4,成员变量的声明次序就是初始化列表的初始化顺序,与初始化的列表顺序无关

试问以下代码输出什么?

#include <iostream>
using namespace std;
class A
{
public:A(int a):_a1(a), _a2(_a1){}void print(){cout << _a1 << " " << _a2;}
private:int _a2;int _a1;
};int main()
{A aa(1);aa.print();return 0;
}

1 随机值

因为声明顺序先_a2,再a1。 初始化时_a1随机值赋给了_a2,而_a1得到1,

static

概念:

声明static的类成员叫静态成员,用static修饰的成员变量叫静态成员变量,用static修饰的成员函数叫静态成员函数,静态成员变量一定要在类外初始化

#include <iostream>
using namespace std;
class A
{
public:A(){_scount++;}A(const A& a){_scount++;}static int Getscount(){return _scount;}~A(){--_scount;}
private:static int _scount;
};int A::_scount = 0;int main()
{cout << A::Getscount() << endl;A a1, a2;A a3(a1);cout << A::Getscount() << endl;return 0;
}

0
3

🚩1,静态成员为所有类对象所共享,不属于某个具体的类对象,存在静态区,所有对象都能调用
2,静态成员变量必须在类外定义,定义时不需要static,类中只是声明
3,静态成员可以用类名::加静态成员访问,也可以类对象.加静态成员访问,
4,静态成员函数
没有this指针
,不能访问任何非静态成员,
5,类中的静态成员也受到public,private限制

问题:
1,静态成员函数可以调用非静态成员函数吗?
不可以,无this指针,非静态成员函数必须通过类对象调用(因为可能访问对象的成员变量
2,非静态成员函数可以调用静态成员函数吗?
可以,静态成员函数全局共享,都可以用,

友元

友元提供了一种突破封装的模式,提供了便利,但使用友元会增加耦合度,所有友元不宜多用,
友元分为:友元函数,友元类,

友元函数

#include <iostream>
using namespace std;
class A
{
public:A(int hour = 10, int minute = 30):_hour(hour),_minute(minute){}ostream& operator<<(ostream& _cout){_cout << _hour <<'-'<< _minute << endl;return _cout;}
private:int _hour;int _minute;
};
int main()
{A a1,a2;a1 << cout; return 0;
}

a1<<cout -> a1.operator<<(&a1,cout)
不符合常规调用,
但是有this指针,所以又不能反过来调用,因为cout<<a1,this指针会和cout抢位置,
🚩实际应用中,cout要在第一个形参位置,所以要将operator重载为全局函数,但是全局函数又访问不了私有成员,所以我们用到友元
🚩友元函数是定义在类外部的普通函数,可以直接访问类的私有成员,不属于任何类,但是要在类内部声明,声明时前面加friend

#include <iostream>
using namespace std;
class A
{friend ostream& operator<<(ostream& _cout, const A& a);friend istream& operator>>(istream& _cin, A& a);
public:A(int hour=10,int minute=40):_hour(hour), _minute(minute){ }private:int _hour;int _minute;
};
ostream& operator<<(ostream& _cout, const A& a)
{_cout << a._hour <<"-" << a._minute << endl;return _cout;
}
istream& operator>>(istream& _cin, A& a)
{_cin >> a._hour >> a._minute;return _cin;
}
int main()
{A a1, a2;cin >> a2;//14 20cout << a1 << a2;return 0;
}

14-20
10-40

说明:
1,友元函数可以直接访问类的私有和保护成员,但不是类的成员函数,
2,友元函数不能被const修饰
3,友元可以定义在类的任何位置,不受访问限定符限制
4,一个函数可以被多个类友元
5,友元函数和普通函数调用相同,

友元类

🚩 1,A类是B类的友元,则A可以访问所有B的私有成员变量,但反过来不行。
🚩 2,友元无传递性,A类是B类的友元,B是C的友元,但A不能访问C类的私有变量,

class Time
{friend class Date;
public:
private:int _hour;int _minute;
};class Date
{
public:void settime(int hour, int minute){_t._hour = hour;_t._minute = minute;}
private:int _year;int _month;int _day;Time _t;
};

内部类

一个类如果定义在另一个类的里面,就叫内部类,内部类属于独立的类,它不属于外部的类,更不能通过外部类访问内部类的成员变量,外部类对内部类没有任何优越权限
注意:
内部类就是外部类的友元,但外部类不是内部的友元

特性
1,内部类可以定义在外部类任何位置,不受访问限定符限定
2,内部类可以直接访问外部的static成员,不需要加类名和.
3,sizeof(外部类)=外部类,和内部类无关

#include <iostream>
using namespace std;
class A
{
public:class B{public:void test(const A& a){cout << k << endl;cout << a.h << endl;}private:};
private:static int k;int h=2;
};
int A::k = 3;
int main()
{A::B t;t.test(A());//隐式对象return 0;
}

再次理解类和对象

总结:类是对某一类实体对象进行描述的,描述对象的各种属性,描述完成后就形成一种新的自定义类型,再通过自定义类型实例化具体对象

http://www.xdnf.cn/news/8717.html

相关文章:

  • 5.25本日总结
  • 计算机网络-WebSocket/DNS/Cookie/Session/Token/Jwt/Nginx
  • DAY36
  • GitLab-CI简介
  • 单链表的排序
  • Collection集合遍历的三种方法
  • multiprocessing多进程使用案例
  • 用神经网络对信贷项目进行预测
  • java三种常见设计模式,工厂、策略、责任链
  • 原生php单元测试
  • bun全栈开发尝鲜:用bun-react-template实现Markdown文章展示
  • removeIf() 方法,结合 Lambda 表达式
  • 鸿蒙仓颉开发语言实战教程:页面跳转和传参
  • WORD 转 PDF 工具:排版 / 图片 / 表格批量转换提升办公效率
  • Acrobat 中 JavaScript 为 PDF 带来的交互
  • 篇章二 数据结构——前置知识(二)
  • C# 正则表达式
  • c/c++的opencv伽马噪声
  • ArrayList 与 LinkedList 区别?
  • 【c++11】智能指针 -- 摆脱内存困扰,现代编程的智能选择
  • OSCP备战-mr-robot靶机详细解法
  • conda 环境中opencv 报错
  • Maven Profile高级策略与冲突解决
  • 手眼标定:九点标定、十二点标定、OpenCV 手眼标定
  • Cursor最新问题不能使用Claude3.7问题的解决方案
  • [Linux]如何配置mailutils郵件服務?
  • 基于STM32的电容电阻测量仪Proteus仿真设计+程序设计+设计报告+讲解视频
  • MyBatis实战指南(三)MyBatis常用配置详解(XML配置,环境配置,类型别名,属性与映射器)
  • 【监控】Prometheus+Grafana 构建可视化监控
  • JVM 的垃圾回收器