C++第20课--初始化列表的使用

本文学习自 狄泰软件学院 唐佐林老师的 C++课程


对象的初始化是指 对正在创建的对象进行初始值设置,对象的初始化是通过构造函数实现的,构造函数中可以完成目标对象的初始状态的设置,包括对象的成员变量的设置等等。但是通过构造函数设置的成员变量不是初始化,而是赋值,是对已经存在的变量进行赋值,并非我们所说的初始化,对象的成员变量的初始化只能通过初始化列表来完成,初始化列表是先于构造函数的函数体执行的,即对创建的变量进行初始值设置。


实验1:类中是否可以存在const成员,可以的话该怎么初始化

实验2:初始化列表的使用

  1. Value 类对象的创建,Value类中只有一个带参构造函数,编译器不会为其添加无参构造函数,所以此处的无参对象会创建失败

  2. 类成员变量只能用初始化列表进行初始化

实验3:const只读成员变量的初始化和修改


在这里插入图片描述

在这里插入图片描述

实验1:类中是否可以存在const成员,可以的话该怎么初始化

随笔:刚开始学到这里,我没懂老师为什么会提出这个问题,我刚开始认为,肯定可以定义啊,但是没有深入思考,怎么初始化。后面想了想才反应过来,我们之前所学习的const标识符在定义的时候就会进行初始化,如 const int c = 0; 此时 c就是一个常量,后面不能出现在赋值符号左边,但是在类中,我们定义成员变量需要在定义对象的时候初始化,不能在类中初始化,所以就会出现这样的情形,const int ci; 定义了一个只读变量,以我们之前学习的知识,后面就没办法对ci进行初始化了,因为无论如何 ci 都不能出现在赋值符号的左边。所以由这个例子就引出了 const 标识符的初始化问题,该怎么初始化 类中的const成员变量。

#include <stdio.h>

class Test
{
private:
    const int ci;
public:
    Test()
    {
        ci = 10;
    }
    int getCI()
    {
        return ci;
    }
};


int main()
{
    Test t;

    printf("t.ci = %d\n", t.getCI());

    return 0;
}

mhr@ubuntu:~/work/c++$ g++ 20-1.cpp
20-1.cpp: In constructor ‘Test::Test()’:
20-1.cpp:8:5: error: uninitialized const member in ‘const int’ [-fpermissive]
     Test()
     ^
20-1.cpp:6:15: note: ‘const int Test::ci’ should be initialized
     const int ci;
               ^
20-1.cpp:10:12: error: assignment of read-only member ‘Test::ci’
         ci = 10;
            ^
mhr@ubuntu:~/work/c++$ 

分析:
提示第8行 Test() 未初始化 const 成员变量
提示第10行 ci = 10; const 成员变量不能出现在赋值符号左边


在这里插入图片描述

在这里插入图片描述


实验2:初始化列表的使用

实验2.1 :Value 类对象的创建,Value类中只有一个带参构造函数,编译器不会为其添加无参构造函数,所以此处的无参对象会创建失败

#include <stdio.h>

class Value
{
private:
    int mi;
public:
    Value(int i)
    {
        printf("i = %d\n", i);
        mi = i;
    }
    int getI()
    {
        return mi;
    }
};

class Test
{

// Value类对象的创建,Value类中只有一个带参构造函数,编译器不会为其添加无参构造函数,所以此处的无参对象会创建失败
private:
    Value m2;
    Value m3;
    Value m1;
public:
    Test() :
    {
        printf("Test::Test()\n");
    }
};


int main()
{
    Test t;

    return 0;
}



mhr@ubuntu:~/work/c++$ g++ 20-2.cpp
20-2.cpp: In constructor ‘Test::Test()’:
20-2.cpp:27:5: error: no matching function for call to ‘Value::Value()’
     {
     ^
20-2.cpp:8:5: note: candidate: Value::Value(int)
     Value(int i)
     ^
20-2.cpp:8:5: note:   candidate expects 1 argument, 0 provided
20-2.cpp:3:7: note: candidate: Value::Value(const Value&)
 class Value
       ^
20-2.cpp:3:7: note:   candidate expects 1 argument, 0 provided
20-2.cpp:27:5: error: no matching function for call to ‘Value::Value()’
     {
     ^
20-2.cpp:8:5: note: candidate: Value::Value(int)
     Value(int i)
     ^
20-2.cpp:8:5: note:   candidate expects 1 argument, 0 provided
20-2.cpp:3:7: note: candidate: Value::Value(const Value&)
 class Value
       ^
20-2.cpp:3:7: note:   candidate expects 1 argument, 0 provided
20-2.cpp:27:5: error: no matching function for call to ‘Value::Value()’
     {
     ^
20-2.cpp:8:5: note: candidate: Value::Value(int)
     Value(int i)
     ^
20-2.cpp:8:5: note:   candidate expects 1 argument, 0 provided
20-2.cpp:3:7: note: candidate: Value::Value(const Value&)
 class Value
       ^
20-2.cpp:3:7: note:   candidate expects 1 argument, 0 provided
mhr@ubuntu:~/work/c++$ 

实验2.2 :类成员变量只能用初始化列表进行初始化

前言:
类成员变量只能用初始化列表进行初始化,不能直接初始化,如下是对象的初始化方式,并不是成员变量的初始化方式,如下

private:
    Test t = 100
    或
    Test t(100)
    或
    Test t = Test(100)

而之前所学习的在构造函数中对成员变量进行赋值,那是赋值操作,并非初始化操作。初始化操作是指 对正在创建的对象的初始值设置

#include <stdio.h>

class Value
{
private:
    int mi;
public:
    Value(int i)
    {
        printf("i = %d\n", i);
        mi = i;
    }
    int getI()
    {
        return mi;
    }
};

class Test
{
//成员的声明顺序 创建顺序
private:
    Value m2;
    Value m3;
    Value m1;
public:
    Test() : m1(1), m2(2), m3(3)
    {
        printf("Test::Test()\n");
    }
};


int main()
{
    Test t;
    
    return 0;
}

mhr@ubuntu:~/work/c++$ 
mhr@ubuntu:~/work/c++$ g++ 20-2.cpp
mhr@ubuntu:~/work/c++$ 
mhr@ubuntu:~/work/c++$ ./a.out 
i = 2
i = 3
i = 1
Test::Test()
mhr@ubuntu:~/work/c++$ 

结果证明 成员变量的初始化,必须通过初始化列表来完成。并且成员的初始化顺序与成员的声明顺序相同,与初始化列表中的位置无关,而且初始化列表先于构造函数函数体执行。

注意区分 初始化列表和构造函数,构造函数是用于对对象的初始化,如果不用构造函数对对象初始化,对象的成员变量的值是未知的。也可以在构造函数中对成员变量进行赋值,但是那并不是初始化,是赋值!!


在这里插入图片描述

const成员的分配的空间是和类对象所分配的空间一致的,如果当前对象是在栈上分配的空间,那么const 成员就是在栈上分配空间。。。。

编译器无法直接得到const成员的初始值,因此无法进入符号表成为真正以意义上的常量。
解析:初始化列表是用于初始化成员变量的,对于const成员变量而言,变量的创建 和 初始化在视觉上是分开的,并不是类似于 const int a=1; 这种写法,所以编译器无法直接确定const标识符的初始值,所以无法进入符号表成为真正意义上的常量,只能是只读变量


实验3:const只读成员变量的初始化和修改

#include <stdio.h>

class Value
{
private:
    int mi;
public:
    Value(int i)
    {
        printf("i = %d\n", i);
        mi = i;
    }
    int getI()
    {
        return mi;
    }
};

class Test
{
private:
    const int ci;
    Value m2;
    Value m3;
    Value m1;
public:
    Test() : m1(1), m2(2), m3(3), ci(100)
    {
        printf("Test::Test()\n");
    }
    int getCI()
    {
        return ci;
    }
    int setCI(int v)
    {
        int* p = const_cast<int*>(&ci);

        *p = v;
    }
};


int main()
{
    Test t;

    printf("t.ci = %d\n", t.getCI());

    t.setCI(10);

    printf("t.ci = %d\n", t.getCI());

    return 0;
}

在这里插入图片描述


在这里插入图片描述

int main()
{
	int i = 0; //初始化
	...
	i=1; //赋值
}

在这里插入图片描述

发布了207 篇原创文章 · 获赞 100 · 访问量 8万+

猜你喜欢

转载自blog.csdn.net/LinuxArmbiggod/article/details/104100943