逗号操作符重载分析(三十三)

我们之前在 C 语言中也学习过了逗号表达式,那么我们就先来再次重新看看逗号表达式。逗号操作符(,)可以构成逗号表达式,逗号表达式用于将多个子表达式连接为一个表达式,它的值为最后一个子表达式的值。逗号表达式中的前 N-1 个子表达式可以没有返回值,它是按照从左向右的顺序计算每个子表达式的值。例如:exp1,exp2,exp3,...,expN

下来我们以代码为例进行逗号表达式的说明

#include <iostream>
#include <string>

using namespace std;

void func(int i)
{
    cout << "void func(int i): " << i << endl;
}

int main()
{
    int i = 0;
    int j = 0;
    int a[3][3] = {
        (0, 1, 2),
        (3, 4, 5),
        (6, 7, 8)
    };
    
    while( i < 5 )
        func(i),
    
    i++;
    
    for(i=0; i<3; i++)
    {
        for(j=0; j<3; j++)
        {
            cout << a[i][j] << endl;
        }
    }
    
    (i, j) = 5;
    
    cout << "i = " << i << endl;
    cout << "j = " << j << endl;
    
    return 0;
}

那么我们在第 21 行定义了一个 while 循环,它的作用域只有下面的一行,按理说它会是个死循环。接下来我们想要打印数组 a 的值,应该打印的是我们定义的值,那么第 34 行这样的赋值会成功吗?我们来看看编译结果

我们看到并没有执行死循环,而是执行了 5 次就退出了。接下来的数组打印也只是打印了 2,5,8。别的都没有打印出来,最后一个是执行成功的。那么我们来分析下,仔细看看第 22 行后面的是逗号,并不是我们平时所定义的分号。所以它和下一句 i++ 结合在一起了,因此便不会是死循环。我们定义数组的时候是 (),而不是 {},因此它将数组中的值当成逗号表达式处理了。最后一个赋值操作也会是当逗号表达式处理,应该是 j 被赋值为 5,经过前面 for 循环,i 则为 3 了。我们接下来将数组 a 中的 () 改成 {} 试试

我们看到它已经成功执行了。那么在 C++ 中重载逗号操作符时合法的,使用全局函数对逗号操作符进行重载。重载函数的参数必须有一个是类类型,重载函数的返回值类型必须是引用。

下来我们以代码为例进行分析

#include <iostream>
#include <string>

using namespace std;

class Test
{
    int mValue;
public:
    Test(int i)
    {
        mValue = i;
    }
    int value()
    {
        return mValue;
    }
};

Test& operator , (const Test& a, const Test& b)
{
    return const_cast<Test&>(b);
    
    return i;
}

Test func(Test& i)
{
    cout << "func(): i =" << i.value() << endl;
}

int main()
{
    Test t0(0);
    Test t1(1);
    Test tt = (t0, t1);
    
    cout << tt.value() << endl;
    
    return 0;
}

我们来看看编译结果

这样看来也没错嘛,那么我们在第 36 行用函数的形式来调用下,别忘了重载的本质就是函数调用。

虽然结果也是对的,但是我们有没有发现它不是从左向右依次执行的,这就和逗号表达式的本意相反了。在 C++ 中通过函数调用扩展操作符的功能后,进入函数体前必须完成所有参数的计算。而函数参数的计算次序是不定的,这便导致了重载后无法严格从左向右计算表达式。所以在工程中,一般是不要重载逗号操作符!!!

通过对逗号操作符重载的学习,总结如下:1、逗号表达式从左向右顺序计算每个子表达式的值;2、逗号表达式的值为最后一个子表达式的值;3、操作符重载无法完全实现逗号操作符的原生意义;4、工程开发中不要重载逗号操作符。

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

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

时间: 2024-11-08 21:26:31

逗号操作符重载分析(三十三)的相关文章

第39课 逗号操作符的分析

1. 逗号操作符 (1)逗号表达式用于将多个子表达式连接为一个表达式 (2)逗号表达式的值为最后一个子表达式的值 (3)逗号表达式的前N-1个子表达式可以没有返回值 (4)逗号表达式按照从左向右的顺序计算每个子表达式的值 exp1,exp2,exp3,…,expN; [实例分析]逗号表达式的示例 #include <iostream> using namespace std; void func(int i) { cout << "func(): i = " &

switch_case,&amp;&amp;,||,条件操作符和逗号操作符,循环语句

一.switch-case switch-case语句主要用在多分支条件的环境中,在这种环境中使用if语句会存在烦琐且效率不高的弊端. switch(expression) { case const expression1: .... case const expression2; ... default: ... } 在执行过程中,expression的值会与每个case的值比较,实现switch语句的功能.关键字case和它所关联的值被称作case标号.每个case标号的值都必须是一个整形常

JavaScript 逗号操作符

让我们从一个有趣的微博开始吧. 末尾的c是优先级最低的逗号操作符.逗号操作符是操作符优先级的最后一行,并且很少有文章记录,它隐藏着它的锋芒.它可能不是JavaScript强势操作符,但是我喜欢它.它简单.优雅并且你应该让它成为你的朋友.所以,我们开始吧--你需要更多了解JavaScript这个害羞英雄. 它是做什么的? 逗号操作符评估它的操作数(从左到右)并返回第二个操作数的值.(MDC) var a = (7, 5); a; //5 var x, y, z; x = (y=1, z=4); x

iOS开发——错误总结篇&amp;开发中常见错误和警告总结(三十三)

开发中常见错误和警告总结(三十三) 动画冲突 错误: Unbalanced calls to begin/end appearance transitions for <uivewcontroller> 解决方法1:去掉动画 解决方法2:监听当前view的动画是否完成 解决方法就是,加一个BOOL型的变量,检查是否在做动画. 1 2 if (transiting) { 3 return; 4 } 5 transiting = YES; 6 [self transitionFromViewCon

NeHe OpenGL教程 第三十三课:TGA文件

转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线教程的编写,以及yarn的翻译整理表示感谢. NeHe OpenGL第三十三课:TGA文件 加载压缩和未压缩的TGA文件: 在这一课里,你将学会如何加载压缩和为压缩的TGA文件,由于它使用RLE压缩,所以非常的简单,你能很快地熟悉它的. 我见过很多人在游戏开发论坛或其它地方询问关于TGA读取的问题.

逗号操作符

不能用逗号操作符将两个声明组合起来,这是因为声明已经将逗号用于其他用途-----分割列表中的变量.例如: int j = 0,i = 3; 到目前为止,逗号操作符最常见的用途是将两个或更多的表达式放到一个for循环表达式中.不过C++还为这个操作符提供了另外两个特性.首先,它确保先计算第一个表达式,然后计算第二个表达式(换句话说,逗号操作符是一个顺序点).如下所示的表达式是安全的: i = 20,j = 2 * i;//i set to 20,j set to 40 其次,C++规定,逗号表达式

JAVA之旅(三十三)——TCP传输,互相(伤害)传输,复制文件,上传图片,多并发上传,多并发登录

JAVA之旅(三十三)--TCP传输,互相(伤害)传输,复制文件,上传图片,多并发上传,多并发登录 我们继续网络编程 一.TCP 说完UDP,我们就来说下我们应该重点掌握的TCP了 TCP传输 Socket和ServiceSocket 建立客户端和服务端 建立连接后,通过Socket中的IO流进行数据的传输 关闭Socket 同样的,我们的客户端和服务端都是两个独立的应用 我们通过查阅API文档发现,该对象在建立的时候,就可以去连接指定主机,因为tcp是面向连接的,所以在建立socket服务时,

【Unity 3D】学习笔记三十三:游戏元素——天空盒子

天空盒子 一般的3D游戏都会有着北京百年一遇的蓝天,让人惊叹不已.其实天空这个效果没有什么神秘的只需用到天空盒子这个组件就行,可以将天空设想成一个巨大的盒子,这个盒子将整个游戏视图和所有的游戏元素包含其中.在unity中制作天空盒子非常方便,只需要像设置其他组件一样设置下就行了.在制作天空盒子之前,我们需要搜集一些天空的贴图,不过,unity很方便的为开发者提供了天空盒子的资源包.首先在project视图中点击鼠标右键,然后选择import package--skyboxes即可添加天空盒子的资

Welcome to Swift (苹果官方Swift文档初译与注解三十三)---235~240页(第五章-- 函数)

Default Parameter Values (参数默认值) 在定义函数的时候,你可以给任何参数定义一个默认的值,如果定义了默认值,在调用这个函数的时候,你可以忽略这个参数. 注意: 设置参数默认值的时候,需要按照函数的参数列表最后的开始,这可以确保在调用函数的时候,即使没默认值的参数也可以按顺序的对应上,也使得函数在调用的时候更加清晰. 下面的代码例子是join函数的新版本,它使用了默认参数: func join(string s1: String, toString s2: String