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

简介: 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();


相关实践学习
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
【涂鸦即艺术】基于云应用开发平台CAP部署AI实时生图绘板
目录
相关文章
|
3月前
|
存储 缓存 监控
用 C++ 红黑树给公司电脑监控软件的日志快速排序的方法
本文介绍基于C++红黑树算法实现公司监控电脑软件的日志高效管理,利用其自平衡特性提升日志排序、检索与动态更新效率,并结合实际场景提出优化方向,增强系统性能与稳定性。
146 4
|
6月前
|
存储 安全 编译器
c++入门
c++作为面向对象的语言与c的简单区别:c语言作为面向过程的语言还是跟c++有很大的区别的,比如说一个简单的五子棋的实现对于c语言面向过程的设计思路是首先分析解决这个问题的步骤:(1)开始游戏(2)黑子先走(3)绘制画面(4)判断输赢(5)轮到白子(6)绘制画面(7)判断输赢(8)返回步骤(2) (9)输出最后结果。但对于c++就不一样了,在下五子棋的例子中,用面向对象的方法来解决的话,首先将整个五子棋游戏分为三个对象:(1)黑白双方,这两方的行为是一样的。(2)棋盘系统,负责绘制画面。
99 0
|
8月前
|
调度
FreeRTOS学习日志 - 第一天
这就是我的FreeRTOS学习日志 - 第一天的内容,明天继续探索这片实时操作系统的广阔海洋。+
167 12
|
10月前
|
存储 缓存 C++
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
|
9月前
|
存储 分布式计算 编译器
C++入门基础2
本内容主要讲解C++中的引用、inline函数和nullptr。引用是变量的别名,与原变量共享内存,定义时需初始化且不可更改指向对象,适用于传参和返回值以提高效率;const引用可增强代码灵活性。Inline函数通过展开提高效率,但是否展开由编译器决定,不建议分离声明与定义。Nullptr用于指针赋空,取代C语言中的NULL。最后鼓励持续学习,精进技能,提升竞争力。
|
12月前
|
算法 网络安全 区块链
2023/11/10学习记录-C/C++对称分组加密DES
本文介绍了对称分组加密的常见算法(如DES、3DES、AES和国密SM4)及其应用场景,包括文件和视频加密、比特币私钥加密、消息和配置项加密及SSL通信加密。文章还详细展示了如何使用异或实现一个简易的对称加密算法,并通过示例代码演示了DES算法在ECB和CBC模式下的加密和解密过程,以及如何封装DES实现CBC和ECB的PKCS7Padding分块填充。
277 4
2023/11/10学习记录-C/C++对称分组加密DES
|
11月前
|
C++ 开发者
C++学习之继承
通过继承,C++可以实现代码重用、扩展类的功能并支持多态性。理解继承的类型、重写与重载、多重继承及其相关问题,对于掌握C++面向对象编程至关重要。希望本文能为您的C++学习和开发提供实用的指导。
169 16
|
编译器 C语言 C++
配置C++的学习环境
【10月更文挑战第18天】如果想要学习C++语言,那就需要配置必要的环境和相关的软件,才可以帮助自己更好的掌握语法知识。 一、本地环境设置 如果您想要设置 C++ 语言环境,您需要确保电脑上有以下两款可用的软件,文本编辑器和 C++ 编译器。 二、文本编辑器 通过编辑器创建的文件通常称为源文件,源文件包含程序源代码。 C++ 程序的源文件通常使用扩展名 .cpp、.cp 或 .c。 在开始编程之前,请确保您有一个文本编辑器,且有足够的经验来编写一个计算机程序,然后把它保存在一个文件中,编译并执行它。 Visual Studio Code:虽然它是一个通用的文本编辑器,但它有很多插
507 6

热门文章

最新文章