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日志并进行多维度分析。
目录
相关文章
|
2月前
|
JSON 安全 API
.net 自定义日志类
在.NET中,创建自定义日志类有助于更好地管理日志信息。示例展示了如何创建、配置和使用日志记录功能,包括写入日志文件、设置日志级别、格式化消息等。注意事项涵盖时间戳、日志级别、JSON序列化、线程安全、日志格式、文件处理及示例使用。请根据需求调整代码。
54 13
|
3月前
|
Java 中间件
SpringBoot入门(6)- 添加Logback日志
SpringBoot入门(6)- 添加Logback日志
76 1
|
3月前
|
Java 中间件
SpringBoot入门(6)- 添加Logback日志
SpringBoot入门(6)- 添加Logback日志
136 5
|
4月前
|
Arthas 监控 Java
JVM知识体系学习七:了解JVM常用命令行参数、GC日志详解、调优三大方面(JVM规划和预调优、优化JVM环境、JVM运行出现的各种问题)、Arthas
这篇文章全面介绍了JVM的命令行参数、GC日志分析以及性能调优的各个方面,包括监控工具使用和实际案例分析。
188 3
|
4月前
|
Python
log日志学习
【10月更文挑战第9天】 python处理log打印模块log的使用和介绍
94 0
|
4月前
|
缓存 Linux 编译器
【C++】CentOS环境搭建-安装log4cplus日志组件包及报错解决方案
通过上述步骤,您应该能够在CentOS环境中成功安装并使用log4cplus日志组件。面对任何安装或使用过程中出现的问题,仔细检查错误信息,对照提供的解决方案进行调整,通常都能找到合适的解决之道。log4cplus的强大功能将为您的项目提供灵活、高效的日志管理方案,助力软件开发与维护。
134 0
|
4月前
|
存储 Prometheus NoSQL
大数据-44 Redis 慢查询日志 监视器 慢查询测试学习
大数据-44 Redis 慢查询日志 监视器 慢查询测试学习
49 3
|
3天前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
1月前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
70 19
|
1月前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
51 13