c++入门学习日志 -- 类 和 对象

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: c++入门学习日志 -- 类 和 对象

初始化列表:

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

  我们知道我们的类里面的成员变量只是变量的声明,然后我们可以认为初始化列表就是我们对象成员变量定义的地方。

6cdddd2171e846e59614faeb791eeeb1.png

我们初始化列表主要是为了那些必须在定义的是初始化的变量准备的:这里的 d1 是对象定义的地方,那我们的成员变量在哪里定义呢,所以就有了初始化列表

大家看如果我不给那些特殊的变量在初始化列表定义会发什么:

class date
{
public:
    date(int year = 1, int month = 1, int day = 1,int tmp = 5,int ret=10)
        :_year(year),
        _month(month)
        /*_tmp(tmp),
        _ret(ret)*/
    {
        _day = day;
    }
private:
    int _year;
    int _month;
    int _day;
    const int _tmp;
    int& _ret;
};
int main()
{
    date d1;
}

7923c1f68750481fa05862392330ce7b.png这里就直接报错了,当然这些特殊的变量是不能在括号里面通过赋值来完成操作的:

date(int year = 1, int month = 1, int day = 1,int tmp = 5,int ret=10)
        :_year(year),
        _month(month)
    {
        _day = day;
        _tmp = tmp;
        _ret = ret;
    }

特殊的成员变量还包括那些需要构造函数需要传参的自定义类型:

class aa
{
public:
    aa(int i)
        :_a(i)
    {}
private:
    int _a;
};
class date
{
public:
    date(int year = 1, int month = 1, int day = 1,int tmp = 5,int ret=10)
        :_year(year),
        _month(month),
        _tmp(tmp),
        _ret(ret),
        _a(1)
    {
        _day = day;
    }
private:
    int _year;
    int _month;
    int _day;
    const int _tmp;
    int& _ret;
    aa _a;
};

在看这样的代码:

class aa
{
public:
    aa(int i = 0)
        :_a(i)
    {}
private:
    int _a;
};
class date
{
public:
    date(int year = 1, int month = 1, int day = 1,int tmp = 5,int ret=10)
        :_year(year),
        _month(month),
        _tmp(tmp),
        _ret(ret),
    {
        _day = day;
    }
private:
    int _year;
    int _month;
    int _day;
    const int _tmp;
    int& _ret;
    aa _a;
};

我们没有在初始化列表里面写自定义类型的定义,它会调用自定义类型的构造函数嘛?

肯定是会的,我们这里只是没有显示的去初始化,但它依旧会去调用的,调用的地方依旧也是初始化列表

总结:其他的变量可以在初始化列表初始化,也可以在函数体内初始化,建议尽量在初始化列表初始化

在定义的地方赋值不是初始化 这个是给缺省值,缺省值也是给我们的的初始化列表使用的,要是显示地初始化就用显示地

1. private:
2. int _year = 1;
3. int _month = 2;
4. int _day = 3;


顺序?

初始化列表里面也是有执行的顺序的,这个顺序是由变量声明的顺序决定的

class date
{
public:
    date(int year = 1, int month = 1, int day = 1,int tmp = 5,int ret=10)
        :_month(month),
         _year(year),
         _tmp(tmp),
         _ret(ret),
    {
        _day = day;
    }
private:
    int _year;
    int _month;
    int _day;
    const int _tmp;
    int& _ret;
    aa _a;
};

看这里就是 _year->_month->_day 的顺序


explicit关键字:

我们知道不同类型的变量变量赋值是会发生隐式类型的转换的,那给自定义类型赋值会不会发生隐式转换呢?

date d1 = 2013;

07623ab67274424c8d10ad9eea69896d.png

 这里是会发生隐式类型的转换的,我们的 整型转换成自定义类型 调用构造函数,紧接着就是拷贝构造了,但是由于编译器优化的原因,这里是直接调用构造函数的,注意我们调用构造函数产生的是一个临时变量(具有常性)

但如果加上explicit关键词,就会报错了,这个关键词意思就是不让进行隐式转换:

6c737018bef8416daff3d75e201101cb.png


静态成员:

class date
{
public:
private:
    static int _year;
    static int _month;
    static int _day;
};

大家觉得这个类的大小是多少呢?

答案是 1 ,我们的静态成员是属于整个类的,是属于所有类的所有对象,是属于静态区的,他也不是在初始化列表里面初始化。我们多个对象访问这个静态变量都是访问的一个变量

class date
{
public:
private:
    static int _year;
    static int _month;
    static int _day;
};
int date::_year = 2012;
int date::_month = 8;
int date::_day = 1;

上面这个是初始化的方式,注意是一定得再外面初始化,不能在声明那里赋值,像非静态成员变量那样给缺省值,这样是不行的

cout << date::_year << endl;

我们可以这样去访问,但是前提是你的成员得是共有的才可以。


  成员函数也是可以设为静态的,静态的成员函数就没有this指针,同样也是可以通过类域去访问这个函数的

 注意:我们静态的成员函数是不能访问静态的成员的。大家知道为什么吗

因为我们的静态成员函数没有this指针,没有this指针怎么去访问呢,大家说是不是


友元类:

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

class tmp
{
public:
  tmp(int hour, int min, int sec)
    :_hour(hour),
    _min(min),
    _sec(sec)
  {
  }
private:
  int _hour;
  int _min;
  int _sec;
};
class date
{
public:
  void print()
  {
    cout << tt._hour << '-' << tt._min << '-' << tt._sec << endl;
  }
private:
  int _year;
  int _month;
  int _day;
  tmp tt;
};


大家看这里我们的打印是会报错的,报的就是这个成员是私有无法访问,像这种情况加个友元类就可以了

class tmp
{
    friend class date;
public:
  tmp(int hour, int min, int sec)
    :_hour(hour),
    _min(min),
    _sec(sec)
  {
  }
private:
  int _hour;
  int _min;
  int _sec;
};
class date
{
public:
  void print()
  {
    cout << tt._hour << '-' << tt._min << '-' << tt._sec << endl;
  }
private:
  int _year;
  int _month;
  int _day;
  tmp tt;
};

这样就相当于告诉我们的tmp: date是它的朋友,可以访问它的私有成员,注意:友元的关系是单向的,友元关系不能传递,假如A是B的友元,然后B是C的友元,这样不能说A是C的友元

一个函数也可以是多个类的友元(写得时候要注意我们的类是向上找的)


内部类:

内部类,顾名思义就是内部定义的一个类,首先这个内部的类是默认为它外面那个类的友元类的。

class date
{
public:
  date(int year = 1, int month = 1, int day = 1) :_year(year), _month(month), _day(day) {}
  class tmp
  {
  public:
    tmp(int hour, int min, int sec)
      :_hour(hour),
      _min(min),
      _sec(sec)
    {
    }
    void print(const date& test)
    {
      cout << test._year << '-' << test._month << '-' << test._day << endl;
    }
  private:
    int _hour;
    int _min;
    int _sec;
  };
private:
  int _year;
  int _month;
  int _day;
};


那大家觉得我们去计算这个类的大小会是多大呢,这个计算需要包括内部类的大小嘛?

答案是不用的,我们计算的依旧只是成员变量的大小(除了static修饰的不计算)


还有一个点要注意:我们的内部类是可以直接访问外部类的static成员的,不需要加类名和对象名


匿名对象?

class tmp
{
public:
    void print()
    {
        cout << _hour << '-' << _min << '-' << _sec << endl;
    }
private:
  int _hour;
  int _min;
  int _sec;
};
int main()
{
    tmp()//这就是一个匿名对象,它的声明周期只存在在这一行,过了这一行它就会自动销毁
}

那我们的匿名对象有什么作用嘛?

当我们想要调用一个类里面的一个函数,我们可能会这样做:

1. tmp d1;
2. d1.print();

但有了匿名对象后就可以这样:

tmp d1().print();


相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
|
14天前
|
算法 网络安全 区块链
2023/11/10学习记录-C/C++对称分组加密DES
本文介绍了对称分组加密的常见算法(如DES、3DES、AES和国密SM4)及其应用场景,包括文件和视频加密、比特币私钥加密、消息和配置项加密及SSL通信加密。文章还详细展示了如何使用异或实现一个简易的对称加密算法,并通过示例代码演示了DES算法在ECB和CBC模式下的加密和解密过程,以及如何封装DES实现CBC和ECB的PKCS7Padding分块填充。
38 4
2023/11/10学习记录-C/C++对称分组加密DES
|
1月前
|
存储 编译器 C语言
【c++丨STL】string类的使用
本文介绍了C++中`string`类的基本概念及其主要接口。`string`类在C++标准库中扮演着重要角色,它提供了比C语言中字符串处理函数更丰富、安全和便捷的功能。文章详细讲解了`string`类的构造函数、赋值运算符、容量管理接口、元素访问及遍历方法、字符串修改操作、字符串运算接口、常量成员和非成员函数等内容。通过实例演示了如何使用这些接口进行字符串的创建、修改、查找和比较等操作,帮助读者更好地理解和掌握`string`类的应用。
53 2
|
1月前
|
存储 编译器 C++
【c++】类和对象(下)(取地址运算符重载、深究构造函数、类型转换、static修饰成员、友元、内部类、匿名对象)
本文介绍了C++中类和对象的高级特性,包括取地址运算符重载、构造函数的初始化列表、类型转换、static修饰成员、友元、内部类及匿名对象等内容。文章详细解释了每个概念的使用方法和注意事项,帮助读者深入了解C++面向对象编程的核心机制。
109 5
|
1月前
|
存储 编译器 C++
【c++】类和对象(中)(构造函数、析构函数、拷贝构造、赋值重载)
本文深入探讨了C++类的默认成员函数,包括构造函数、析构函数、拷贝构造函数和赋值重载。构造函数用于对象的初始化,析构函数用于对象销毁时的资源清理,拷贝构造函数用于对象的拷贝,赋值重载用于已存在对象的赋值。文章详细介绍了每个函数的特点、使用方法及注意事项,并提供了代码示例。这些默认成员函数确保了资源的正确管理和对象状态的维护。
105 4
|
1月前
|
XML 安全 Java
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
本文介绍了Java日志框架的基本概念和使用方法,重点讨论了SLF4J、Log4j、Logback和Log4j2之间的关系及其性能对比。SLF4J作为一个日志抽象层,允许开发者使用统一的日志接口,而Log4j、Logback和Log4j2则是具体的日志实现框架。Log4j2在性能上优于Logback,推荐在新项目中使用。文章还详细说明了如何在Spring Boot项目中配置Log4j2和Logback,以及如何使用Lombok简化日志记录。最后,提供了一些日志配置的最佳实践,包括滚动日志、统一日志格式和提高日志性能的方法。
394 30
【日志框架整合】Slf4j、Log4j、Log4j2、Logback配置模板
|
19天前
|
监控 安全 Apache
什么是Apache日志?为什么Apache日志分析很重要?
Apache是全球广泛使用的Web服务器软件,支持超过30%的活跃网站。它通过接收和处理HTTP请求,与后端服务器通信,返回响应并记录日志,确保网页请求的快速准确处理。Apache日志分为访问日志和错误日志,对提升用户体验、保障安全及优化性能至关重要。EventLog Analyzer等工具可有效管理和分析这些日志,增强Web服务的安全性和可靠性。
|
2月前
|
XML JSON Java
Logback 与 log4j2 性能对比:谁才是日志框架的性能王者?
【10月更文挑战第5天】在Java开发中,日志框架是不可或缺的工具,它们帮助我们记录系统运行时的信息、警告和错误,对于开发人员来说至关重要。在众多日志框架中,Logback和log4j2以其卓越的性能和丰富的功能脱颖而出,成为开发者们的首选。本文将深入探讨Logback与log4j2在性能方面的对比,通过详细的分析和实例,帮助大家理解两者之间的性能差异,以便在实际项目中做出更明智的选择。
343 3
|
29天前
|
存储 监控 安全
什么是事件日志管理系统?事件日志管理系统有哪些用处?
事件日志管理系统是IT安全的重要工具,用于集中收集、分析和解释来自组织IT基础设施各组件的事件日志,如防火墙、路由器、交换机等,帮助提升网络安全、实现主动威胁检测和促进合规性。系统支持多种日志类型,包括Windows事件日志、Syslog日志和应用程序日志,通过实时监测、告警及可视化分析,为企业提供强大的安全保障。然而,实施过程中也面临数据量大、日志管理和分析复杂等挑战。EventLog Analyzer作为一款高效工具,不仅提供实时监测与告警、可视化分析和报告功能,还支持多种合规性报告,帮助企业克服挑战,提升网络安全水平。
|
2月前
|
存储 缓存 关系型数据库
MySQL事务日志-Redo Log工作原理分析
事务的隔离性和原子性分别通过锁和事务日志实现,而持久性则依赖于事务日志中的`Redo Log`。在MySQL中,`Redo Log`确保已提交事务的数据能持久保存,即使系统崩溃也能通过重做日志恢复数据。其工作原理是记录数据在内存中的更改,待事务提交时写入磁盘。此外,`Redo Log`采用简单的物理日志格式和高效的顺序IO,确保快速提交。通过不同的落盘策略,可在性能和安全性之间做出权衡。
1717 14
|
1月前
|
存储 监控 安全
什么是日志管理,如何进行日志管理?
日志管理是对IT系统生成的日志数据进行收集、存储、分析和处理的实践,对维护系统健康、确保安全及获取运营智能至关重要。本文介绍了日志管理的基本概念、常见挑战、工具的主要功能及选择解决方案的方法,强调了定义管理目标、日志收集与分析、警报和报告、持续改进等关键步骤,以及如何应对数据量大、安全问题、警报疲劳等挑战,最终实现日志数据的有效管理和利用。
128 0