初始化列表的使用(十五)

我们之前在 C 语言中可以定义 const 成员,那么我们是否可以在类中定义 const 成员呢?我们来看看下面代码中的类定义是否合法呢?如果合法,ci 的值是什么,存储在哪里呢?

#include <stdio.h>

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

int main()
{
    Test t;
    
    printf("t.ci = %d\n", t.getCI());
    
    return 0;
}

照我们之前学习的知识可以猜测对象 t 是创建于栈上,那么它中的 ci 便会是随机值了。我们看看编译结果

编译报错,它说我们没有初始化 ci,下面我们在它定义的时候并初始化为10。也就是将第 6 行改为 const int ci = 10;我们再次看看它是否编译通过

我们看到编译产生警告了,虽然它的运行结果是正确的。我们之前说过,一个优秀的程序员会将任何一个警告都看作是错误,因为它的结果将是不确定的。这样写是由问题的,洽好 g++ 编译器支持这样写,我们不能写出依赖于某种编译器特性的代码。所以这时便会用到初始化列表了,在 C++ 中提供了初始化列表对成员变量进行初始化,它的语法规则如下

那么我们在程序中加上构造函数并用初始化列表进行初始化,如下

Test() : ci(5)
{    
}

我们再次编译,如下

我们看到编译器没有报任何警告,这便证明了在 C++ 中提供了初始化列表对成员变量进行初始化。那么我们在这块有几个注意事项:a> 成员的初始化顺序与成员的声明顺序相同;b> 成员的初始化顺序与初始化列表中的位置无关;c> 初始化列表先于构造函数的函数体执行。为例更加形象的说明,我们再次以代码为例进行说明

#include <stdio.h>

class Value
{
private:
    int mi;
public:
    Value(int i)
    {
        printf("i = %d\n", i);
        
        mi = i;
    }
    int getMI()
    {
        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;
}

我们在 Test 类中定义了 3 个 Value 对象,然后在构造函数中使用了初始化列表对他们进行初始化。在构造函数中我们加入了一条打印语句,按照我们之前讲的,应该在初始化完了之后再打印那条语句。我们编译看看结果

我们看到打印的是如我们分析的那样,但是前面初始化的顺序好像不太一样,我们是按照 m1、m2、m3 这样的顺序进行初始化的。想想我们之前说的:初始化的顺序和它声明的顺序相同,和它的位置并无关。所以看看我们声明顺序就知道打印的是正确的了。

类中的 const 成员会被分配空间的,它的本质是只读变量并且只能在初始化列表中指定初始值。编译器无法直接得到 const 成员的初始值,因此无法进入符号表成为真正意义上的常量。我们以代码为例进行说明

#include <stdio.h>

class Test
{
private:
    const int ci;
public:
    Test() : ci(10)
    {
        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(100);
    
    printf("t.ci = %d\n", t.getCI());
    
    return 0;
}

我们看看编译结果是否改变了 ci 的值

我们看到已经成功的通过指针 + const_cast去掉了它的 const 属性,也就是说,它只是一个具有只读属性的变量。我们再次强调下,初始化与赋值不同。初始化是对正在创建的对象进行初值设置,而赋值则是对已经存在的对象进行值设置。通过对初始化列表的学习,总结如下:1、类中可以使用初始化列表对成员进行初始化;2、初始化列表先于构造函数体执行;3、类中可以定义 const 成员变量,const 成员变量必须在初始化列表中指定初值,const 成员变量为只读变量。

欢迎大家一起来学习 C++ 语言,可以加我QQ:243343083。

原文地址:http://blog.51cto.com/12810168/2117669

时间: 2024-11-09 00:29:43

初始化列表的使用(十五)的相关文章

十八、初始化列表的使用

1.类中定义const成员,及其初始化 #include <stdio.h> class Test { private: const int ci; // 编译通过,类中可以用const来修饰 public: int getCI() { return ci; } }; int main() { Test t; // 定义t对象的时候,报错说ci没有初始化 printf("t.ci = %d\n", t.getCI()); return 0; } 如何初始化类里面的const

C++(二十八) — 构造函数的初始化列表

1.解决的问题: 在 B 类中,组合了一个 A 类对象,其中A类设计了构造函数.由于构造函数的调用规则,设计了构造函数就必须调用,但在定义B类时没有机会初始化A,因此采用构造函数的初始化列表来解决.  2.构造和析构调用顺序 先执行被组合对象的构造函数,如果组合对象有多个,则按照定义顺序,而不是按照初始化列表顺序.   析构函数,和构造函数的调用顺序相反. 举例如下: class A { public: A(int a_) { a = a_; cout << "A的构造函数,a: &

c++11之初始化列表

一.前言 C++的学习中,我想每个人都被变量定义和申明折磨过,比如我在大学笔试过的几家公司,都考察了const和变量,类型的不同排列组合,让你区别有啥不同.反正在学习C++过程中已经被折磨惯了,今天再来看看重温下那段"辉煌的历史".先来看一段代码: Player pa; // (a) Player pb(); // (b) Player pc = Player(); // (c) Player pd(Player()); // (d) pd = Player() // (e) a,b,

x264代码剖析(十五):核心算法之宏块编码中的变换编码

x264代码剖析(十五):核心算法之宏块编码中的变换编码 为了进一步节省图像的传输码率,需要对图像进行压缩,通常采用变换编码及量化来消除图像中的相关性以减少图像编码的动态范围.本文主要介绍变换编码的相关内容,并给出x264中变换编码的代码分析. 1.变换编码 变换编码将图像时域信号变换成频域信号,在频域中图像信号能量大部分集中在低频区域,相对时域信号,码率有较大的下降. H.264对图像或预测残差采用4×4整数离散余弦变换技术,避免了以往标准中使用的通用8×8离散余弦变换逆变换经常出现的失配问题

第十五章 文件属性类的实现

                  第十五章    文件属性类的实现        根用户的权限也不能是无限大.必须考虑到保护用户的隐私!用户的文件内容.程序代码可设置为根用户也不能观看,只能是文件拥有者可以查看.修改.但根用户可以删除一切非根用户的文件.也可以查看用户的目录.所以,i_mode字符更改如下:      BU16 i_mode; // 描述文件的访问权限:文件的读.写.执行权限  // i_mode.15-13  ftype; 文件类型: 0-符号软连接文件, // 1-硬连接文

[WebGL入门]十五,为多边形涂抹颜色(顶点颜色的指定)

注:文章译自http://wgld.org/,原作者杉本雅広(doxas),文章中如果有我的额外说明,我会加上[lufy:],另外,鄙人webgl研究还不够深入,一些专业词语,如果翻译有误,欢迎大家指正. 本次的demo的运行结果 增加顶点属性的个数 上次,终于绘制了一个三角形,但是只绘制了一个纯白色的多边形.这次,给多边形的顶点中添加颜色属性,基本上做的事情和上一篇文章一样,只是稍微增加点步骤而已.首先,就像以前多次重复的那样,顶点可以包含很多种情报(参考:顶点缓存和基础),而且每一个情报叫做

第十五章 链表

/** 数组与链表的区别:数组易随机访问,链表易插入和删除 链表组成:储存数据元素的数据域,储存下一结点地址的指针域 链表易于插入与删除 lists 的用法????????????????????? *///建立一个图书链表 #include<iostream> #include <string> using namespace std; struct book //第一步: 用于建立节点. class 默认为私有 struct 默认为公有 //节点组成:①数据域 ②指针域(*ne

hbase 学习(十五)缓存机制以及可以利用SSD作为存储的BucketCache

下面介绍Hbase的缓存机制: a.HBase在读取时,会以Block为单位进行cache,用来提升读的性能 b.Block可以分类为DataBlock(默认大小64K,存储KV).BloomBlock(默认大小128K,存储BloomFilter数据).IndexBlock(默认大小128K,索引数据,用来加快Rowkey所在DataBlock的定位) c.对于一次随机读,Block的访问顺序为BloomBlock.IndexBlock.DataBlock,如果Region下面的StoreFi

QT开发(六十五)——QT样式表编程实例

QT开发(六十五)--QT样式表编程实例 一.QComboBox组合框样式定制 1.基本定义 QComboBox  {     border: 1px solid gray;     border-radius: 3px;     padding: 1px 2px 1px 2px;  # 针对于组合框中的文本内容     min-width: 9em;   # 组合框的最小宽度 } QComboBox::drop-down {     subcontrol-origin: padding;