c++6.0编译java运算符重载的重载时 结果不正确的问题

c++ 输出运算符重载问题,我用的是vc,编译时有问题,求解答_百度知道
c++ 输出运算符重载问题,我用的是vc,编译时有问题,求解答
&&c: Complex(int i=0;i& return 0,Complex&);+&};iostream,Complex& c){ output&class Complex{& (ostream&&&&lt,int j=0){real=i;a;&&&lt.real&friend ostream& operator &c;&quot.imag&endl,&lt.h& cout&}int main(){ C} friend ostream& operator &imag=j; (ostream&; &&quot: & &&lt#include&lt
;streamb: use of undefined type &#39: ambiguous symbole: 'streamb: error C2027;streamoff&#39: function &#39: &#39.h(90) :&#92.h(90) : see declaration of &#39.h(67) ;vc98\ios'include\include\include\vc98\ already has a bodye:\vc98&#92.h(4) ;ios&#39: ambiguous symbole;vc98&#92: error C2084:\include\int __cdecl main(void)&#39:\streampos&#39:\include\vc98\ .h(90) : error C2872;streambe: error C2872
提问者采纳
&ostream& operator&&&c: Complex(int i=0;i& return 0,Complex&);&};/class Complex{&lt,Complex& c)/去掉friend{ output& &quot.real&lt,int j=0){real=i;a;&&+&c;&&&lt.imag&endl,&lt.h& cout&}int main(){ C} friend ostream& operator &imag=j; (ostream&; &&quot: && (ostream& output#include&lt
e:\vc98\include\ios.h(4) : error C2084: function 'int __cdecl main(void)' already has a bodye:\vc98\include\streamb.h(90) : error C2872: 'streampos' : ambiguous symbole:\vc98\include\streamb.h(90) : error C2872: 'streamoff' : ambiguous symbole:\vc98\include\streamb.h(90) : error C2027: use of undefined type 'ios'改了还是显示了这样的问题
#include&iostream&class Complex{public: Complex(int i=0,int j=0){real=i;imag=j;} friend ostream& operator && (ostream&,Complex&);private: double real,};ostream& operator&& (ostream& output,Complex& c)//去掉friend{ output&&& &&&c.real&&&+&&&c.imag&&&i&&& }int main(){ C cout&&a; return 0;}
提问者评价
是我的编译器出问题了......
其他类似问题
为您推荐:
运算符重载的相关知识
其他2条回答
把友元函数放到类体内
e:\vc98\include\ios.h(4) : error C2084: function 'int __cdecl main(void)' already has a bodye:\vc98\include\streamb.h(90) : error C2872: 'streampos' : ambiguous symbole:\vc98\include\streamb.h(90) : error C2872: 'streamoff' : ambiguous symbole:\vc98\include\streamb.h(90) : error C2027: use of undefined type 'ios'改了还是显示了这样的问题,怎么办?
重新建个工程再编译一下
在类外定义友元函数时,不需要加关键 friend。
e:\vc98\include\ios.h(4) : error C2084: function 'int __cdecl main(void)' already has a bodye:\vc98\include\streamb.h(90) : error C2872: 'streampos' : ambiguous symbole:\vc98\include\streamb.h(90) : error C2872: 'streamoff' : ambiguous symbole:\vc98\include\streamb.h(90) : error C2027: use of undefined type 'ios'改了还是显示了这样的问题
莫非用的是 vc 6.0?
珍惜生命,远离 VC 6。
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁收藏,1.8k 浏览
问题对人有帮助,内容完整,我也想知道答案
问题没有实际价值,缺少关键内容,没有改进余地
自己写了一个matrix的模板类, 但是在重载运算符时,出现问题了。
下面是matrix类:
// matrix.h -- A
#ifndef __MATRIX_H_
#define __MATRIX_H_
#include &iostream&
#include &ostream&
#include &fstream&
#include &string&
#include &cstring&
#include &cmath&
#include &vector&
#include &iomanip&
template &typename T&
class matrix {
vector&vector&T&&
matrix(int nRow = 2, int nCol = 2){
data.resize(nRow);
for (int i = 0; i & nR i++) {
data[i].resize(nCol);
cout && "Default Constructor" &&
matrix(matrix&T& & c):data(c.data){
cout && "Copy Constructor" &&
matrix(matrix&T& &&c):data(std::move(c.data)){
cout && "Move Constructor" && }
matrix&T& operator = (matrix&T& &c);
matrix&T& operator = (matrix&T& &&c){
data = move(c.data);
cout && "Move Assignment" &&
int row(){ return data.size();} // Get row of the matrix.
int col(){ return (row() ? data[0].size() : 0);} // Get col of the matrix.
bool is_empty(){return (row() == 0);} // check if the matrix is empty.
bool is_square(){return (!is_empty()) && (row() == col());} // check if the matrix is a square matrix.
void resize(int nrow, int ncol); // Resize matrix
void display(); // print matrix.
T &operator()(int i, int j){
if ((i & 0) || (i &= row())||(j & 0)||(j &=col())) {
cerr && "(" && i && "," && j && ") Out of Range" &&
return data[i][j];
matrix&T& operator + (matrix&T& &c);
matrix&T& operator - (matrix&T& &c);
matrix&T& operator * (matrix&T& &c);
matrix&T& operator / (matrix&T& &c);
matrix&T& operator += (matrix&T& &c);
matrix&T& operator -= (matrix&T& &c);
matrix&T& operator *= (matrix&T& &c);
matrix&T& operator /= (matrix&T& &c);
matrix&T& operator + (matrix&T& &&c);
matrix&T& operator - (matrix&T& &&c);
matrix&T& operator * (matrix&T& &&c);
matrix&T& operator / (matrix&T& &&c);
matrix&T& operator += (matrix&T& &&c);
matrix&T& operator -= (matrix&T& &&c);
matrix&T& operator *= (matrix&T& &&c);
matrix&T& operator /= (matrix&T& &&c);
template&typename U& friend std::ostream &operator&& (std::ostream &out,
matrix&T& &c);
~matrix(){
cout && "Free done" &&
template &typename T&
matrix&T& matrix&T&:: operator = (matrix&T& &c){
if (this == &c) {
if( row() != c.row()){
int nrow = row();data.resize(c.row());
if ((row() & c.row()) && (col() != c.col())) {
for (int i = 0; i & c.row(); i++) {
data[i].resize(c.col());
if ((row() & c.row()) && (col() == c.col())) {
for (int i = row(); i & c.row(); i++) {
data[i].resize(c.col());
for (int i = 0; i & c.row(); i++) {
for (int j = 0; j & c.col(); j++) {
data[i][j] = c.data[i][j];
cout && "Copy Assignment" &&
template &typename T&
void matrix&T&:: resize(int nrow, int ncol){
if ((row() == nrow) && (col() == ncol)) {
if ((row() == nrow) && (col() != ncol)) {
for (int i = 0; i & i++) {
data[i].resize(ncol);
if ((row() != nrow) && (col() == ncol)) {
data.resize(nrow);
if (row() & nrow) {
for (int i = row(); i & i++) {
data[i].resize(ncol);
if ((row() != nrow) && (col() != ncol)) {
data.resize(nrow);
for (int i = 0; i & i++) {
data[i].resize(ncol);
template &typename T&
void matrix&T&:: display(){
cout && "Row = " && row() && "\tCol = " && col() &&
cout.precision(10);
for (int i = 0; i & row(); i++) {
for (int j = 0; j & col(); j++) {
cout && setw(8) && data[i][j] && " ";
template &typename T&
matrix&T& matrix&T&:: operator + (matrix&T& &c){
if ((row() != c.row()) || (col() != c.col())) {
cerr && "Dimensions of matrices besides + don't match! Exit!!!" &&
matrix&T& temp(c.row(),c.col());
for (int i = 0; i & c.row(); i++) {
for (int j = 0; j & c.col(); j++) {
temp(i,j) = data[i][j] + c(i,j);
cout && "Copy Add" &&
template &typename T&
matrix&T& matrix&T&:: operator + (matrix&T& &&c){
if ((row() != c.row()) || (col() != c.col())) {
cerr && "Dimensions of matrices besides + don't match! Exit!!!" &&
matrix&T& temp(c.row(),c.col());
for (int i = 0; i & c.row(); i++) {
for (int j = 0; j & c.col(); j++) {
c(i,j) += data[i][j];
cout && "Move Add" &&
template &typename T&
matrix&T& matrix&T&:: operator - (matrix&T& &c){
if ((row() != c.row()) || (col() != c.col())) {
cerr && "Dimensions of matrices besides + don't match! Exit!!!" &&
matrix&T& temp(row(),col());
for (int i = 0; i & row(); i++) {
for (int j = 0; j & col(); j++) {
temp(i,j) = data[i][j] - c(i,j);
template &typename T&
matrix&T& matrix&T&:: operator - (matrix&T& &&c){
if ((row() != c.row()) || (col() != c.col())) {
cerr && "Dimensions of matrices besides + don't match! Exit!!!" &&
for (int i = 0; i & row(); i++) {
for (int j = 0; j & col(); j++) {
c(i,j) = data[i][j] - c(i,j);
template &typename T&
std::ostream &operator && (std::ostream &out,
matrix&T& &c){
if(c.is_empty()){
for (int i = 0; i & c.row(); i++) {
for (int j = 0; j & c.col(); j++) {
out && setw(8) && c(i,j) && " ";
#endif /* __MATRIX_H_ */
但在调用时,
#include &iostream&
#include "matrix.h"
int main(int argc, const char *argv[]) {
matrix&double& my(3,3);
my(2,2) = 2.12;
cout && endl &&
matrix&double& aaa(my);
cout && endl &&
matrix&double& bbb(my);
cout && endl &&
bbb = aaa + my +
cout && endl &&
matrix&double& ccc = aaa + my +
cout && endl && endl &&
matrix&double& ddd=
cout && endl &&
matrix&double& eee(aaa + bbb);
cout && endl &&
结果却是这样:
Default Constructor
Copy Constructor
Copy Constructor
Default Constructor
Default Constructor
Move Assignment
Copy Constructor
Default Constructor
Default Constructor
Copy Constructor
Copy Assignment
Copy Constructor
Default Constructor
移动构造函数并没有执行,
matrix&double& eee(aaa + bbb);
这里有两次复制构造,一次复制赋值, 本应该是移动构造的,太奇怪了。还有很多问题,大都与这有关。这是怎么回事呢?
答案对人有帮助,有参考价值
答案没帮助,是错误的答案,答非所问
我跑了一下(加了两行cout),matrix&double& eee(aaa + bbb);对应的输出是,
Default Constructor
Copy Constructor
Copy Assignment
Copy Constructor
所以,没有“两次复制构造,一次复制赋值”,而是“一次默认构造,一次矩阵加法”,也即以下代码:
template &typename T&
matrix&T& matrix&T&:: operator + (matrix&T& &c){
matrix&T& temp(c.row(),c.col());
cout && "Copy Add" &&
所以问题是,为什么矩阵加法返回了临时变量(右值引用),但eee却没有调用移动构造函数?
我认为,这里是编译器进行了更古老的一个处理——,把矩阵加法的返回值直接构造在了eee上,省去了temp。
“典型地,当一个函数返回一个对象实例,一个临时对象将被创建并通过复制构造函数把目标对象复制给这个临时对象。C++标准允许省略这些复制构造函数,即使这导致程序的不同行为,即使编译器把两个对象视作同一个具有副作用。”——引自前述返回值优化维基百科
至于为什么返回值优化会优先于移动构造函数执行,我不知道原因。我能提供的信息是,返回值优化在C++98(1998年)里已经有了,移动构造(右值引用)在C++11(2011年)里才有。
同步到新浪微博
分享到微博?
与我们一起探索更多的未知
专业的开发者技术社区,为用户提供多样化的线上知识交流,丰富的线下活动及给力的工作机会
加入只需一步
关闭理由:
删除理由:
忽略理由:
推广(招聘、广告、SEO 等)方面的内容
与已有问题重复(请编辑该提问指向已有相同问题)
答非所问,不符合答题要求
宜作评论而非答案
带有人身攻击、辱骂、仇恨等违反条款的内容
无法获得确切结果的问题
非开发直接相关的问题
非技术提问的讨论型问题
其他原因(请补充说明)
举报理由:
推广(招聘、广告、SEO 等)方面的内容
带有人身攻击、辱骂、仇恨等违反条款的内容
与已有问题重复(请编辑该提问指向已有相同问题)
不友善内容
答非所问,不符合答题要求
其他原因(请补充说明)
补充说明:
扫扫下载 App
SegmentFault
一起探索更多未知  上一节主要讲解了C++里运算符重载函数,在看了单目运算符(++)重载的示例后,也许有些朋友会问这样的问题。++自增运算符在C或C++中既可以放在操作数之前,也可以放在操作数之后,但是前置和后置的作用又是完全不同的(q前置运算符:先加1,再赋值;后置运算符:先赋值,再加1)。那么要怎么重载它们,才可以有效的区分开来呢?今天我就来说说C++中是怎么处理前置运算符和后置运算符的重载的。以及介绍一下插入运算符(&&)和提取运算符(&&)的重载。
  1.在C++里编译器是根据运算符重载函数参数表里是否插入关键字int来区分前置还是后置运算。比如:
1 #include "stdafx.h" 2 #include &iostream& 3
4 class TDPoint//三维坐标 5 { 6 private: 7 int 8 int 9 int10 public:11
TDPoint(int x=0,int y=0,int z=0)12
{13 this-&x=x;14 this-&y=y;15 this-&z=z;16
TDPoint operator++();//成员函数重载前置运算符++18
TDPoint operator++(int);//成员函数重载后置运算符++19
friend TDPoint operator++(TDPoint& point);//友元函数重载前置运算符++20
friend TDPoint operator++(TDPoint& point,int);//友元函数重载后置运算符++21 void showPoint();22 };23 24 TDPoint TDPoint::operator++()25 {26 ++this-&x;27 ++this-&y;28 ++this-&z;29 return*this;//返回自增后的对象30 }31 32 TDPoint TDPoint::operator++(int)33 {34
TDPoint point(*this);35 this-&x++;36 this-&y++;37 this-&z++;38 return//返回自增前的对象39 }40 41 TDPoint operator++(TDPoint& point)42 {43 ++point.x;44 ++point.y;45 ++point.z;46 return//返回自增后的对象47 }48 49 TDPoint operator++(TDPoint& point,int)50 {51
TDPoint point1(point);52
point.x++;53
point.y++;54
point.z++;55 return point1;//返回自增前的对象56 }57 58 void TDPoint::showPoint()59 {60
std::cout&&"("&&x&&","&&y&&","&&z&&")"&&std::61 }62 63 int main()64 {65
TDPoint point(1,1,1);66
point.operator++();//或++point67
point.showPoint();//前置++运算结果68 69
point=point.operator++(0);//或point=point++70
point.showPoint();//后置++运算结果71 72 operator++(point);//或++73
point.showPoint();//前置++运算结果74 75
point=operator++(point,0);//或point=point++;76
point.showPoint();//后置++运算结果77 78 return0;79 }
从示例代码里可以清楚的看出,后置运算符重载函数比前置运算符重载函数多了一个int类型的参数,这个参数只是为了区别前置和后置运算符,此外没有任何作用。所以在调用后置运算符重载函数时,int类型的实参可以取任意值。
  2.在C++中,操作符"&&"和"&&"被定义为左位移运算符和右位移运算符。由于在iostream头文件中对它们进行了重载,使得它们可以用基本数据的输出和输入。
#include "stdafx.h"#include &iostream&int main(){
std::cout&&"a="&&a&&std:://运算符"&&"重载后用于输出
a=a&&2;//右移运算符
std::cout&&"右移2位:a="&&a&&std::
std::cout&&"请输入一个整数a:";
std::cin&&a;//运算符"&&"重载后用于输入
a=a&&2;//左移运算符
std::cout&&"左移2位:a="&&a&&std::
插入运算符"&&"是双目运算符,左操作数为输出流类ostream的对象,右操作数为系统预定义的基本类型数据。头文件iostrem对其重载的函数原型为ostream& operator&&(ostream& ,类型名);类型名就是指基本类型数据。但如果要输出用户自定义的类型数据的话,就需要重载操作符"&&",因为该操作符的左操作数一定为ostream类的对象,所以插入运算符"&&"只能是类的友元函数或普通函数,不能是其他类的成员函数。一般定义格式:
  ostream& operator&&(ostream& ,自定义类名&);
提取运算符"&&"也是如此,左操作数为istream类的对象,右操作数为基本类型数据。头文件iostrem对其重载的函数原型为istream& operator&&(istream& ,类型名);提取运算符也不能作为其他类的成员函数,可以是友元函数或普通函数。它的一般定义格式为:
  istream& operator&&(istream& ,自定义类名&);
我还是用上一节用的Complex类(复数类)来举例:
#include "stdafx.h"#include &iostream&class Complex //复数类{
private://私有double//实数double//虚数public:
Complex(double real=0,double imag=0)
this-&real=
this-&imag=
friend std::ostream&operator&&(std::ostream& o,Complex& com);//友元函数重载提取运算符"&&"
friend std::istream&operator&&(std::istream& i,Complex& com);//友元函数重载插入运算符"&&"};std::ostream&operator&&(std::ostream& o,Complex& com){
std::cout&&"输入的复数:";
if(com.imag&0)
if(com.imag!=0)
o&&com.imag&&"i"&&std::
return}std::istream&operator&&(std::istream& i,Complex& com){
std::cout&&"请输入一个复数:"&&std::
std::cout&&"real(实数):";
std::cout&&"imag(虚数):";
return}int main(){
std::cin&&
std::cout&&
阅读(...) 评论()重载运算符时编译出错,高手请进,在线等!
[问题点数:0分]
重载运算符时编译出错,高手请进,在线等!
[问题点数:0分]
不显示删除回复
显示所有回复
显示星级回复
显示得分回复
只显示楼主
2005年4月 C/C++大版内专家分月排行榜第二
本帖子已过去太久远了,不再提供回复功能。Swift教程之运算符重载
招聘信息:
原文地址:(raywenderlich)&作者:Corinne Krych &译者:孟祥月():在早前的iOS 8盛宴系列的教程里,你已经了解到,Swift提供了许多强大的、现代的编程特性,比如泛型、函数式编程、一等类型(first class)的枚举、结构体等特性。但是现在还有另外一个Swift的特性,你应该知道并且会爱上它,它就是运算符重载。这是一个很好的方法,你能使用+、-、*、/等操作符作用在你喜欢的任何类型上面。如果你有一定的创造性,你甚至可以定义属于你自己的操作符。例如:我们在代码中使用运算符重载去讲多个CGPoints对象相加,例如下面代码:let&pt1&=&CGPoint(x:&10,&y:&20)
let&pt2&=&CGPoint(x:&-5,&y:&0)
let&pt3&=&pt1&+&pt2
let&pt4&=&pt3&*&100方便吧?那就马上开始重载吧,增强你的Swift开发的能力吧。注意:这个Swift的教程是假设你已经具备了基础的Swift开发能力。如果你是新接触Swift,我们建议你先去学习我们的其他的.运算符:概述注意:这一部分的内容是可选的,如果你想回顾一下运算符及其优先级,还是可以看这部分内容的。如果你已经对这些很熟悉了,可以直接创建一个空的playground,进行下一部分内容:重载(Overloading)。首先我们创建一个新的playground来帮助你去了解运算符。添加如下的代码在你的playground中:var&simpleSum&=&1&+&3你能看到我们希望的结果:4这里有两个我们熟悉的操作符:首先,你定义了一个叫做simpleSum的变量,并且使用赋值操作符(=)设置了它的值。然后,你使用加操作符(+)计算了两个整数的和。在这篇教程里,你将像这样重载操作符。但是首先,你需要理解优先级的概念。优先级你可能还记得在学校里的数学课上学过的关于操作符的优先级的规则。这些规则使某些操作符比其他得操作符有一个更高的优先级,高优先级的操作符被优先计算。例如乘会在加或者减之前计算。在你的playground中输入以下的代码,验证在Swift中是否也遵循这些规则。var&sumWithMultiplication&=&1&+&3&-&3&*&2你能看到如下的结果:-2当算数操作符有相同的优先级的时候,Swift从左到右去计算这些操作符。在这个例子中,运算符按照如下的顺序计算的:1.3 * 2:减去(译者注:这个减去可以忽略,主要是为了对应第三步)2.1 + 3:因为在操作符优先级一样得情况下,优先计算最左边得操作符。3.4 - 6:这个运算完全依赖于前面高优先级的运算符的运算结果。注意:如果你想了解Swift中优先级的列表,你能在找到完成的运算符优先级的列表。加法不仅仅适用于整数整数运算会按照我们希望的运行,但是你能将+使用到其他的类型上吗?下面代码证明了,你可以!在你的playground里面添加如下的代码试一试:var&sumArray&=&[1,&2]&+&[1,&2]在这种情况下,Swift将+解释成为append指令。但是如果你是想把每一个位置的元素相加怎么办呢?我们都知道这个叫做向量加法(vector addition)。当然,你能自己定义一个方法去实现这个功能,在你的playground添加如下的代码再试一试:func&add(left:&[Int],&right:&[Int])&->&[Int]&{
&&&&var&sum&=&[Int]()&
&&&&assert(left.count&==&right.count,&"vector&of&same&length&only")&
&&&&for&(key,&v)&in&enumerate(left)&{
&&&&&&&&sum.append(left[key]&+&right[key])&
&&&&return&sum
}这样你就定义了一个全局的方法,这个方法实现了计算输入的两个数组的相加,首先检测两个输入的数组的长度是否一致,然后将两个数组每一个位置上的元素相加并且存储到一个新的数组里面。现在添加下面的代码,验证一下你的新方法是否工作正常:var&arr1&=&[1,&1]
var&arr2&=&[1,&1]
var&arr3&=&add(arr1,&arr2)你将在控制台看到如下的输出:[2,&2]它很棒!但是我们必须去调用一个方法去做这件事,为什么我们不可以使用+运算符代替呢?运算符重载运算符重载允许你改变现在的作用在特定在的结构体和类上的已经存在的操作符的工作方式(译者注:可能有点乱)。这个不正是你想要的吗--改变+操作符作用在int数组上的方式。因为运算符重载是作用在playground的全局中的,所以新建一个playground,防止影响你原来写的例子。然后添加如下的代码到你的playground:func&+(left:&[Int],&right:&[Int])&->&[Int]&{&//&1
&&&&var&sum&=&[Int]()&//&2
&&&&assert(left.count&==&right.count,&"vector&of&same&length&only")&&//&3
&&&&for&(key,&v)&in&enumerate(left)&{
&&&&&&sum.append(left[key]&+&right[key])&//&4
&&&&return&sum
}你已经定义了一个全局的函数,叫做+,它将两个int数组相加然后返回一个int数组。下面分解一下它是怎么工作的:注意这个方法定义没有什么特殊。它是一个普通的方法定义,除了你使用了+作为它的函数名。你创建了一个空的Int数组。这个例子只能工作在两个数组是相同的情况上,所以这里使用assert保证它是这样。然后你枚举了左侧的数组,并且加上了右边的数组在相同位置的值。在你的playground添加如下的代码,测试一下这个方法:var&sumArray1&=&[1,&2,&3]&+&[1,&2,&3]最终--你期望的向量相加操作符结果出现了!你将看到如下的结果:[2,&4,&6]当然,运算符重载并不都是愉快的。当一个人查看你的代码,他们希望操作符的默认行为,这时候运算符重载会使他们迷惑。虽然这样,但是还是不能阻止你重写+运算符让它去执行数字的减法,当然这样的风险是明显的。记住运算符重载的原则:能力越大责任越大典型的,当你在一个新的对象上重载运算符的时候,需要保持它原始的语义,而不是定义不同(和让人费解)的行为。在这个例子中,重载的行为还是保持了原始的语义:向量加法仍然是一种加法。但是当你覆盖了Int数组默认的加行为的时候,过了几个月你可能想要使用Int数组加得默认行为,这个将会使用感到很困惑。幸运的是Swift让你能够定义属于你自己的自定义的运算符。定义自定义运算符这里有三个步骤去定义一个自定义操作符:命名你的运算符选择一种类型设置它的优先级和结合性定义你的运算符现在你必须选择一个字符作为你的运算符。自定义运算符可以以/、=、-、+、!、*、%、、&、|、^、~或者Unicode字符开始。这个给了你一个很大的范围去选择你的运算符。但是别太高兴,选择的时候你还必须考虑重复输入的时候更少的键盘键入次数。在这种情况下,你可以复制粘贴Unicode字符⊕作为很好适应你例子里面加法的实现。选择一种类型在Swift中你能定义一元、二元和三元的操作符。他们表明了运算符操作的数字的数目。一元操作符与一个操作数相关,比如后置++(i++)或者前置++(++i),他们依赖于运算符与操作数出现的位置。二元操作符是插入的,因为它出现在两个操作符中间,比如1 + 1。三元操作符有三个操作数。在Swift中,?:条件操作符是唯一一个三目运算符,比如a?b:c。你应该基于你的运算符的操作数的个数选择合适得类型。你想要实现两个数组相加,那就定义二元运算符。设置它的优先级和结合性由于运算符定义是全局的,所以你要小心的选择你的自定义运算符的优先级和结合性。这个是十分棘手的,所以有一个比较好的方法,在中找到一个类似的标准的运算符,然后使用相同的语义。例如,在定义向量加的时候,可以使用与+运算符相同的优先级和结合性。编写你的自定义运算符回到你的playground,输入下面代码去定义你的自定义运算符。为了简单,你可能想去复制粘贴⊕。(译者注:这里可能指的是在使用的过程中去复制这个字符)infix&operator&⊕&{&associativity&left&precedence&140&}&//&1
func&⊕(left:&[Int],&right:&[Int])&->&[Int]&{&//&2
&&&&var&sum&=&[Int](count:&left.count,&repeatedValue:&0)
&&&&assert(left.count&==&right.count,&"vector&of&same&length&only")
&&&&for&(key,&v)&in&enumerate(left)&{
&&&&&&&&sum[key]&=&left[key]&+&right[key]
&&&&return&sum
}这段代码与你前面在第一部分中的重载类似,这段代码主要做了以下几个步骤:定义一个中缀/二元操作符,它有两个操作数并且位于操作符两侧。命名操作符为⊕。设置结合性为left,表明该操作符在相同优先级时候,将使用操作符的顺序从左到右结合。设置优先级为140,这个是和Int加法有相同的优先级,这些优先级可以在查看。在第二部分的代码和你在前面看到的类似,它按照两个数组的顺序将其一个一个的相加。在你的playground中添加下面的代码,测试这个新的运算符:var&sumArray&=&[1,&2,&3]&⊕&[1,&2,&3]你将看到和前面重载方法一样的结果,但是这次你有了一个拥有不同语义的操作符。奖励内容现在你已经知道了怎么去创建一个自定义的运算符,是时候挑战一下你自己了。你已经创建了一个⊕运算符去执行向量的相加,所以使用现在的知识去创建一个?操作符,使用相似的方法实现两个数组的减法。尽你最大的努力,然后再去查看下面的答案。infix&operator&&?&{&associativity&left&precedence&140&}
func&?(left:&[Int],&right:&[Int])&->&[Int]&{
&&var&minus&=&[Int](count:&left.count,&repeatedValue:&0)
&&assert(left.count&==&right.count,&"vector&of&same&length&only")
&&for&(key,&v)&in&enumerate(left)&{
&&&&minus[key]&=&left[key]&-&right[key]
&&return&minus
}测试:var&subtractionArray&=&[1,&2,&3]&?&[1,&2,&3]记住相似的操作符如果你定义了一个新的操作符,不要忘了定义任何相关得运算符。例如,加等运算符(+=)组合了加和赋值两个运算符成为了一个运算符。由于你的新的运算符语义上是跟加是一样的,一个好的方法是也定义一个加等于运算符。添加下面得代码到Operator2.playground:infix&operator&&⊕=&{&associativity&left&precedence&140&}&//&1
func&⊕=(inout&left:&[Int],&right:&[Int])&{&//&2
&&&&left&=&left&⊕&right
}第一行是与⊕运算符一样得声明,它使用了一个组合运算符。需要注意第二行,声明这个组合运算符的左侧输入参数为inout,这个表示这个参数的值,将会在运算符方法内部直接被修改。作为一个结果,这个运算符不用返回一个值,它直接修改了你的输入值。在你的playground添加如下的代码,测试这个运算符是否按照你想的方法运行。你将在控制台看到如下输出:[3,&5,&7]现在看看,定义你自己的运算符一点也不难。为更多类型定义运算符现在想象你也想为小数定义一个向量加运算符。一种方式是你按照为Int重载运算符的方式,为Double和Float重载一个新的运算符。它仅仅是几行的代码,但是你必须使用复制/粘贴。如果你像我一样--有代码洁癖--复制代码不是你的第一选择,它会使你的代码很难维护。使用泛型来解救幸运的,Swift泛型能帮助你实现这个功能。如果你需要复习一下Swift的泛型,可以找到我们之前发布的文章。为了有一个干净的上下文环境,我们新建一个playground。添加如下的代码到你的playground中:infix&operator&⊕&{&associativity&left&precedence&140&}
func&⊕(left:&[T],&right:&[T])&->&[T]&{&//&1
&&&&var&minus&=&[T]()
&&&&assert(left.count&==&right.count,&"vector&of&same&length&only")
&&&&for&(key,&v)&in&enumerate(left)&{
&&&&&&&&minus.append(left[key]&+&right[key])&//&2
&&&&return&minus
}在第一行,你定义了一个泛型类型得函数⊕,它有一个类型占位符T。到这里playground不高兴了。你能看到一个编译错误:Could not find an overload for '+' that accepts the supplied arguments.这个错误来源于第二行,当我们尝试使用+运算符作用在两个类型为T得left和right两个参数上的时候发生错误。Swift并不知道它应该怎么使用+运算符作用在这些参数上,因为它不知道这些参数是什么类型。扩展一个协议去掉你的代码,并且用下面的代码代替:protocol&Number&{&&//&1
&&&&func&+(l:&Self,&r:&Self)&->&Self&//&2
extension&Double&:&Number&{}&//&3
extension&Float&&:&Number&{}
extension&Int&&&&:&Number&{}
infix&operator&⊕&{&associativity&left&precedence&140&}
func&⊕(left:&[T],&right:&[T])&->&[T]&{&//&4
&&&&var&minus&=&[T]()
&&&&assert(left.count&==&right.count,&"vector&of&same&length&only")
&&&&for&(key,&v)&in&enumerate(left)&{
&&&&&&&&minus.append(left[key]&+&right[key])
&&&&return&minus
}你在这里做了许多的事情,我们回过头来分解一下这些步骤:你定义了一个协议Number这个Number定义了一个运算符+你为Double、Float和Int创建了一个扩展,使它们能够实现Number协议你使用了一个类型约束去要求T必须实现Number协议最后,你告诉编译器,T应该怎么去处理+运算符。既然你已经修复了编译错误,那就使用下面得代码分别使用Double数组和Int数组测试一下吧:var&doubleArray&=&[2.4,&3.6]&⊕&[1.6,&2.4]
var&intArray&=&[2,&4]&⊕&[1,&2]你将在控制台看到如下输出:[4.0,&6.0]
[3,&6]现在这个运算符能够正常在多种数据类型下面工作,并且没有复制代码。如果你想添加更多得数字类型,你只需要简单的生命其实现Number协议就可以了。实际工作中如何使用运算符重载难道你就没有想过,如果它没有作用,我会让你浪费这么多的时间在这篇教程上吗?这一部分将要展示给你一个真实得例子,让你了解怎么样在你的项目中更好得使用运算符重载。运算符和CGPoints对于这个Demo,你将使用,它是一个方便得Sprite Kit帮助类的集合,当时是为了这本书的第二版而写的。你能在github上找到这个框架的仓库。在你命令行界面输入如下的代码,可以Clone一份这个仓库的分支:git clone /raywenderlich/SKTUtils.git --branch swift你在上下载下来的是该仓库分支的压缩包zip。注意:从Xcode6 beta 5开始,在playground中引入你自己的library成为了可能。你需要做的就是将框架和playground绑定在一个workspace中。如果你想知道更多关于这些的内容,请阅读这篇文章。打开SKUTils/Examples/Playground/SKUTils.xcodeworkspace,并且编译这个项目。然后从项目导航里面打开MyPlayground.playground。删除现在里面的内容并且添加如下的代码:import&SKTUtils&
let&pt1&=&CGPoint(x:&10,&y:&20)
let&pt2&=&CGPoint(x:&-5,&y:&0)
let&pt3&=&pt1&+&pt2&
let&pt4&=&pt3&*&100你可能很惊讶,你已经在CGPoint上成功的使用+、*运算符,并且编译器并没有出现错误。{x&10&y&20}
{x&-5&y&0}
{x&5&y&20}
{x&500&y&2,000}这个魔法来自于你在头部引入的SKTUtils。让我们仔细的看一下。在SKTUtils中的重载在项目导航中打开SKTUtils/CGPoint+Extension.swift文件。你将看到为CGPoint定义了一个扩展,重载了+和+=运算符。public&func&+&(left:&CGPoint,&right:&CGPoint)&->&CGPoint&{
&&return&CGPoint(x:&left.x&+&right.x,&y:&left.y&+&right.y)
public&func&+=&(inout&left:&CGPoint,&right:&CGPoint)&{
&&left&=&left&+&right
}这段代码跟你前面写的类似,只是把访问控制符设置成了public。访问控制符约束着在其他得源文件和模块中能否访问到你的代码。由于SKTUtils是一个框架,所以它需要能够被它自己模块之外访问到,所以定义为了public。这个戏法解释清楚了,它没有一点魔力,只是一个聪明得编码。当然,在游戏中CGPoint加法和乘法也是一个很普通得运算,所以在那本书中,重载了CGPoint的运算符简化了代码,使它简洁、易读。我相信你能在你的项目中发现类似的例子。运算符重载是Swift的一个强大得特性,如果你小心的使用它,它会使你的开发更加高效。接下来该做什么?你已经到了这个教程的结尾,我希望你喜欢它!你能在找到最终的playground。如果你想学习更多关于运算符重载和Swift的知识,可以查看我们的新书。我希望你找到一种方法,在你的项目中使用运算符重载!但是记住:with great power comes great responsibility(能力越大责任越大) – don’t be Troll Dev!&如果你对于这个教程或者运算符重载有什么问题,可以在下面加入我们的论坛讨论。
微信扫一扫
订阅每日移动开发及APP推广热点资讯公众号:CocoaChina
点击量12949点击量11655点击量10211点击量9169点击量5515点击量4948点击量4768点击量4633点击量4531
&2015 Chukong Technologies,Inc.
京公网安备89}

我要回帖

更多关于 java运算符重载 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信