❶ c++重载运算符
C++中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类).
// 同上,内置的运算符 只能应用于内置的数据类型 ...比如 int char double .等等。
(一) C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
// 就是说只能重载内置的 + - * / 等运算符,不能自己创造运算符计算。 。
(二) C++允许重载的运算符C++中绝大部分的运算符允许重载.
不能重载的运算符只有5个:
(1) 成员访问运算符.
(2) 作用域运算符∷
(3) 条件运算符?:
(4) 成员指针运算符*
(5) 编译预处理命令的开始符号#
(三) 重载不能改变运算符运算对象(即操作数)的个数。
// 不能改变运算符运算对象, 比如+法运算符,那么它有两个操作数 ..当我们重载它的时候 也只能有两个操作数 。
(四) 重载不能改变运算符的优先级别。
// 重载完之后并不能改变它的优先级别,比如 +号, 无论你怎么设计重载函数. 它永远不可能比()的优先级高......
(五) 重载运算符的函数不能有默认的参数,否则就改变了运算符参数的个数,与前面第(3)点矛盾。
// 于上面3..同。
(六) 重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。也就是说,参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。
// 重载的参数不能全部是C++内置数据类型。 至少要有一个是自定义类型。因为如果我们定义的是两个内置的类型 就会跟系统所定义的冲突。 因为当我们使用内置的运算符时,那么编译器其实也是调用的一个重载运算符进行计算。这是编译器自动添加的。 如果我们也定义的相同 那么肯定会产生冲突。
(七) 用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载。
① 赋值运算符(=)可以用于每一个类对象,可以利用它在同类对象之间相互赋值。
② 地址运算符&也不必重载,它能返回类对象在内存中的起始地址。
// 前面已经说过,C++内置运算符只能计算内置的数据类型 。所以当我们要使用自定义类型时 就必须要进行重载..
总之,当C++语言原有的一个运算符被重载之后,它原先所具有的语义并没有消失,只相当于针对一个特定的类定义了一个新的运算符。
运算符重载可以使用成员函数和友元函数两种形式。可以参考以下的经验:
(1)只能使用成员函数重载的运算符有:=、()、[]、->、new、delete。
(2)单目运算符最好重载为成员函数。
(3) 对于复合的赋值运算符如+=、-=、*=、/=、&=、!=、~=、%=、>>=、<<=建议重载为成员函数。
(4) 对于其它运算符,建议重载为友元函数。
运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。重载运算符的函数一般格式如下:
函数类型 operator 运算符名称 (形参表列)
{
对运算符的重载处理
}
重载为类成员函数时参数个数=原操作数个数-1
(后置++、--除外)
// 当重载为类成员函数时,参数个数等于原来的操作数-1 ..比如 对象a +对象b ..我们重载的时候需要两个操作数 a 和b 但我们传递过去一个就可以了 , 比如 a+b 我们只需要把b传递过去就可以了。因为当调用重载运算符时 就是a调用的重载运算符,那么它就是当前对象 它就是这时的this 指针 ..而且类成员函数只能使用两个类中成员...
重载为友元函数时 参数个数=原操作数个数,且至少应该有一个自定义类型的形参。
//与上面没多大区别,但它却可以调用非类中对象.. 比如调用一个对象a+1 ..注意的是即使定义为友元函数,它的操作数也必须有一个为自定义类型。
看一个实例:
#include<iostream>
using namespace std;
class complex //复数类声明
{
public: //外部接口
complex(double r=0.0,double i=0.0)
{
real=r;
imag=i;
} //构造函数
complex operator + (complex c2); //+重载为成员函数
complex operator - (complex c2); //-重载为成员函数
void display(); //输出显示复数
private: //私有数据成员
double real; //复数实部
double imag; //复数虚部
};
complex complex::operator +(complex c2) //重载函数实现
{
complex c;
c.real=real+c2.real;
c.imag=imag+c2.imag;
return complex(c.real,c.imag);
}
complex complex::operator -(complex c2) //重载函数实现
{
complex c;
c.real=real-c2.real;
c.imag=imag-c2.imag;
return complex(c.real,c.imag);
}
void complex::display()
{ cout<<"("<<real<<","<<imag<<"i"<<")"<<endl; }
int main() //主函数
{
complex c1(5,4),c2(2,10),c3; //声明复数类的对象
cout<<"c1="; c1.display();
cout<<"c2="; c2.display();
c3=c1-c2; //使用重载运算符完成复数减法
cout<<"c3=c1-c2=";
c3.display();
c3=c1+c2; //使用重载运算符完成复数加法
cout<<"c3=c1+c2=";
c3.display();
system("pause");
return 0;
}
程序输出的结果为:
c1=(5,4i)
c2=(2,10i)
c3=c1-c2=(3,-6i)
c3=c1+c2=(7,14i)
通过代码我们可以看出: 定义了两个成员函数重载运算符..重载了+ 和- . 当我们使用这个类的两个成员进行相加的或者相减的时候就会自动调用重载的运算符..使用我们在重载的运算符中所定义的操作。那我们可以看到,在进行+或者-的时候是把两个对象中保存的复数的值进行加减 然后返回了。 要注意的是并不是+号和减号被完全改变了,而只是这个类中的对象在进行+ -操作的时候才会调用重载.
我们来测试一下; 我们在main()函数中再定义三个变量 ,int a=5,b=3,c; c=a-b ; 然后再输出c的值 ,我们发现输出为2 . .这也证明了我们所定义的重载运算符并没有改变它原来的功能..而是赋予了它多重的含义..
那我们再来看下运算符重载在友元函数中的使用。
我们只需要将complex complex::operator +(complex c2) //重载函数实现
{
complex c;
c.real=real+c2.real; // real 代表 this->real 其实就是代表传递进来的当前对象.
c.imag=imag+c2.imag;
return complex(c.real,c.imag);
}
这段代码 修改一下... 改为 complex friend complex::operator +(complex c2 complex c3)
那么同样也可以完成相同的功能..而且还更容易扩充..因为从上面得知..重载的运算符必须和用户定义的自定义类型的对象一起使用. 也就是说至少有一个自定义类型..或者是它的引用..如果我们使用成员运算符重载的话只能使用类中的对象成员..而使用友元运算符重载那么我们则可以使用类外的数据..当我们需要使用的时候直接修改为 complex friend complex::operator +(complex c2 int a) 如这样的形式就可以了。
❷ 关于C++重载运算符
所谓重载,就是重新赋予新的含义。函数重载就是对一个已有的函数赋予新的含义,使之实现新功能。
运算符也可以重载
运算符重载是对已有的运算符赋予多重含义
必要性
C++中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)
(一) C++不允许用户自己定义新的运算符,只能对已有的C++运算符进行重载。
(二) C++允许重载的运算符C++中绝大部分的运算符允许重载.
不能重载的运算符只有5个:
(1) 成员访问运算符.
(2) 作用域运算符∷
(3) 条件运算符?:
(4) 成员指针运算符*
(5) 编译预处理命令的开始符号#
(三) 重载不能改变运算符运算对象(即操作数)的个数。
(四) 重载不能改变运算符的优先级别。
(五) 重载运算符的函数不能有默认的参数,否则就改变了运算符参数的个数,与前面第(3)点矛盾。
(六) 重载的运算符必须和用户定义的自定义类型的对象一起使用,其参数至少应有一个是类对象(或类对象的引用)。也就是说,参数不能全部是C++的标准类型,以防止用户修改用于标准类型数据的运算符的性质。
(七) 用于类对象的运算符一般必须重载,但有两个例外,运算符“=”和“&”不必用户重载。
① 赋值运算符(=)可以用于每一个类对象,可以利用它在同类对象之间相互赋值。
② 地址运算符&也不必重载,它能返回类对象在内存中的起始地址。
总之,当C++语言原有的一个运算符被重载之后,它原先所具有的语义并没有消失,只相当于针对一个特定的类定义了一个新的运算符。
运算符重载可以使用成员函数和友元函数两种形式。可以参考以下的经验:
(1)只能使用成员函数重载的运算符有:=、()、[]、->、new、delete。
(2)单目运算符最好重载为成员函数。
(3) 对于复合的赋值运算符如+=、-=、*=、/=、&=、!=、~=、%=、>>=、<<=建议重载为成员函数。
(4) 对于其它运算符,建议重载为友元函数。
运算符重载的方法是定义一个重载运算符的函数,在需要执行被重载的运算符时,系统就自动调用该函数,以实现相应的运算。也就是说,运算符重载是通过定义函数实现的。运算符重载实质上是函数的重载。重载运算符的函数一般格式如下:
函数类型 operator 运算符名称 (形参表列)
{
对运算符的重载处理
}
重载为类成员函数时参数个数=原操作数个数-1
(后置++、--除外)
重载为友元函数时 参数个数=原操作数个数,且至少应该有一个自定义类型的形参。
将“+”、“-”运算重载为复数类的成员函数。
规则:
实部和虚部分别相加减。
操作数:
两个操作数都是复数类的对象。
#include<iostream>
using namespace std;
class complex //复数类声明
{
public: //外部接口
complex(double r=0.0,double i=0.0)
{
real=r;
imag=i;
} //构造函数
complex operator + (complex c2); //+重载为成员函数
complex operator - (complex c2); //-重载为成员函数
void display(); //输出显示复数
private: //私有数据成员
double real; //复数实部
double imag; //复数虚部
};
complex complex::operator +(complex c2) //重载函数实现
{
complex c;
c.real=real+c2.real;
c.imag=imag+c2.imag;
return complex(c.real,c.imag);
}
complex complex::operator -(complex c2) //重载函数实现
{
complex c;
c.real=real-c2.real;
c.imag=imag-c2.imag;
return complex(c.real,c.imag);
}
void complex::display()
{ cout<<"("<<real<<","<<imag<<“i”<<")"<<endl; }
void main() //主函数
{ complex c1(5,4),c2(2,10),c3; //声明复数类的对象
cout<<"c1="; c1.display();
cout<<"c2="; c2.display();
c3=c1-c2; //使用重载运算符完成复数减法
cout<<"c3=c1-c2=";
c3.display();
c3=c1+c2; //使用重载运算符完成复数加法
cout<<"c3=c1+c2=";
c3.display();
}
程序输出的结果为:
c1=(5,4i)
c2=(2,10i)
c3=c1-c2=(3,-6i)
c3=c1+c2=(7,14i)
在本程序中对运算符“+”,”-”进行了重载,使之能用于两个复数的相加减。在该例中运算符重载函数operator+ ,operator-作为Complex类中的成员函数。
“+” ,”-”是双目运算符,为什么在程序中的重载函数中只有一个参数呢?实际上,运算符重载函数有两个参数,由于重载函数是Complex类中的成员函数,有一个参数是隐含的,运算符函数是用this指针隐式地访问类对象的成员。
可以看到,重载函数operator+访问了两个对象中的成员,一个是this指针指向的对象中的成员,一个是形参对象中的成员。如this->real+c2.real,this->real就是c1.real。
在将运算符函数重载为成员函数后,如果出现含该运算符的表达式,如c1+c2,编译系统把它解释为c1.operator+(c2)
即通过对象c1调用运算符重载函数,并以表达式中第二个参数(运算符右侧的类对象c2)作为函数实参。运算符重载函数的返回值是Complex类型,返回值是复数c1和c2之和(Complex(c1.real + c2.real,c1.imag+c2.imag))。
仔细看下吧 你的问题都在里面 这是我们的PPT
❸ C++中的运算符重载,帮我详细介绍下
运算符重载是对已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据导致不同类型的行为。运算符重载的实质就是函数重载。在实现过程中,首先把指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参,然后根据实参的类型来确定需要调用的函数,这个过程是在编译过程中完成的。
一、运算符重载的作用
运算符重载为类的用户提供了更直观的接口,使类类型的对象也可以像普通变量一样进行运算符的表达式运算。运算符重载允许C/C++的运算符在用户定义类型(类)上拥有一个用户定义的意义。
二、运算符重载的规则
(1)C++中的运算符除了少数几个以外,全部可以重载,而且只能重载已有的运算符。
可以重载的运算符有:
算术运算符:+,-,*,/,%,++,--;
位操作运算符:&,|,~,^,<<,>>
逻辑运算符:!,&&,||;
比较运算符:<,>,>=,<=,==,!=;
赋值运算符:=,+=,-=,*=,/=,%=,&=,|=,^=,<<=,>>=;
其他运算符:[],(),->,,(逗号运算符),new,delete,new[],delete[],->*。
不能重载的运算符只有5个:
类属关系运算符“.”,成员指针运算符“*”,作用域分辨符“::”,sizeof运算符和三目运算符“?:”。
(2)重载之后运算符的优先级和结合性都不变。
(3)四个“不能改变”
·不能改变运算符操作数的个数;
·不能改变运算符原有的优先级;
·不能改变运算符原有的结合性;
·不能改变运算符原有的语法结构。
(4)至少要有一个操作对象是自定义类型。
(5)重载的运算符含义必须清楚,不能有二义性。
三、运算符重载的2种方法
(1)运算符重载为成员函数
(a)对于双目运算符op,如果要重载op为某类的成员函数,使之能够实现表达式 k op t,其中k为A类的对象,则应当把op重载为A类的成员函数,该函数只有一个形参,形参的类型是t所属的类型。经过这样重载之后,表达式 k op t 就相当于函数调用k.operator op( t )
(b)对于前置单目运算符U(如负号“-”),若要重载U为类的成员函数,用来实现表达式
U oprd,其中oprd为A类的对象,则U应当重载为A类的成员函数,且该函数不带形参。经过重载之后,表达式U oprd 就相当于函数调用oprd.operator U()。
(b)后置运算符“++”和“--”,若要将它们重载为类的成员函数,用来实现表达式oprd++或oprd--,其中oprd为A类的对象,那么就应当重载这2个运算符为A类的成员函数,这时函数要带有一个整型(int)形参。重载之后,表达式 oprd ++ 和 oprd -- 就分别相当于函数调用oprd.operator ++(0) 和 oprd.operator --(0)。
(2)运算符重载为友元函数
(a)对于双目运算符op,如果它的一个操作数为类A的对象,就可以将op重载为A类的友元函数,该函数有两个形参,其中一个形参的类型是A类。经过这样的重载之后,表达式k op t就相当于函数调用operator op( k, t )
(b)对于前置单目运算符U(如负号“-”),若要实现表达式 U oprd 其中oprd为A类的对象,则U可以重载为A类的友元函数,函数的形参为A类的对象oprd。经过重载之后,表达式
U oprd 就相当于函数调用operator U( oprd )
(c)对于后置运算符“++”和“--”,如果要实现表达式 oprd ++ 或 oprd --, 其中oprd为A类的对象,那么运算符就可以重载为A类的友元函数,这时函数的形参有两个,一个是A类的对象oprd,另一个是整型(int)形参。第二个参数是用于与前置运算符函数相区别的。重载之后,表达式oprd ++ 和 oprd -- 就分别相当于函数调用operator ++ (oprd, 0)
和operator -- (oprd, 0)。
❹ 操作符的重载方法
//使用成员函数重载运算符
#include <iostream>
using namespace std;
class example
{
private:
int val;
public:
example(int v = 0) { val = v; }
void setval(int v) { val = v; }
int getval() { return val; }
example operator +(example);
};
//成员函数重载运算符只需要一个参数,执行时由表达式左边的对象调用函数
example example::operator +(example o)
{
example t(val + o.val);
return t;
}
int main()
{
example ex1(3), ex2, ex3;
ex2.setval(5);
ex3 = ex1 + ex2; //由ex1调用函数
cout << ex3.getval() << endl;
return 0;
}
//使用友元函数重载运算符,主函数同上
class example
{
private:
int val;
public:
example(int v = 0) { val = v; }
void setval(int v) { val = v; }
int getval() { return val; }
friend example operator +(example, example);
};
//友元函数重载运算符需要两个参数,可以直接访问类的私有数据成员
example operator +(example o1, example o2)
{
example t(o1.val + o2.val);
return t;
}
//使用普通函数重载运算符,主函数同上
class example
{
private:
int val;
public:
example(int v = 0) { val = v; }
void setval(int v) { val = v; }
int getval() { return val; }
};
//普通函数重载运算符需要两个参数,不能直接访问类的私有数据成员
example operator +(example o1, example o2)
{
example t(o1.getval() + o2.getval());
return t;
}
❺ 运算符重载的方法,运算符重载函数有哪几类,常用的是那两类
运算符重载函数有成员函数和友元函数两类。
有些运算符随便用二者之一实现重载,例如+
有些运算符只能用友元函数重载,例如<<
有些运算符只能用成员函数重载,例如=
❻ C++中如何重载整型运算符
//尝试下面这种重载运算符的方法:
#include<iostream>
usingnamespacestd;
classPower{
public:
Power(intx){
oper_num=x;
}
friendintoperator^(Power&x,Power&y);//重载运算符作为友元函数
private:
intoper_num;
};
intoperator^(Power&x,Power&y){
if(y.oper_num==0)return1;
if(y.oper_num==1)returnx.oper_num;
return(int)pow(double(x.oper_num),double(y.oper_num));
}
intmain()
{
Powerx(4),y(2);
intresult=x^y;
cout<<result<<endl;
return0;
}
❼ Python正确重载运算符的方法示例详解
Python正确重载运算符的方法示例详解
说到运算符重载相信大家都不陌生,运算符重载的作用是让用户定义的对象使用中缀运算符(如 + 和 |)或一元运算符(如 - 和 ~)。说得宽泛一些,在 Python 中,函数调用(())、属性访问(.)和元素访问 / 切片([])也是运算符。
我们为 Vector 类简略实现了几个运算符。__add__ 和 __mul__ 方法是为了展示如何使用特殊方法重载运算符,不过有些小问题被我们忽视了。此外,我们定义的Vector2d.__eq__ 方法认为 Vector(3, 4) == [3, 4] 是真的(True),这可能并不合理。下面来一起看看详细的介绍吧。
运算符重载基础
在某些圈子中,运算符重载的名声并不好。这个语言特性可能(已经)被滥用,让程序员困惑,导致缺陷和意料之外的性能瓶颈。但是,如果使用得当,API 会变得好用,代码会变得易于阅读。Python 施加了一些限制,做好了灵活性、可用性和安全性方面的平衡:
不能重载内置类型的运算符
不能新建运算符,只能重载现有的
某些运算符不能重载——is、and、or 和 not(不过位运算符
&、| 和 ~ 可以)
前面的博文已经为 Vector 定义了一个中缀运算符,即 ==,这个运算符由__eq__ 方法支持。我们将改进 __eq__ 方法的实现,更好地处理不是Vector 实例的操作数。然而,在运算符重载方面,众多比较运算符(==、!=、>、<、>=、<=)是特例,因此我们首先将在 Vector 中重载四个算术运算符:一元运算符 - 和 +,以及中缀运算符 + 和 *。
一元运算符
-(__neg__)
一元取负算术运算符。如果 x 是 -2,那么 -x == 2。
+(__pos__)
一元取正算术运算符。通常,x == +x,但也有一些例外。如果好奇,请阅读“x 和 +x 何时不相等”附注栏。
~(__invert__)
对整数按位取反,定义为 ~x == -(x+1)。如果 x 是 2,那么 ~x== -3。
支持一元运算符很简单,只需实现相应的特殊方法。这些特殊方法只有一个参数,self。然后,使用符合所在类的逻辑实现。不过,要遵守运算符的一个基本规则:始终返回一个新对象。也就是说,不能修改self,要创建并返回合适类型的新实例。
对 - 和 + 来说,结果可能是与 self 同属一类的实例。多数时候,+ 最好返回 self 的副本。abs(...) 的结果应该是一个标量。但是对 ~ 来说,很难说什么结果是合理的,因为可能不是处理整数的位,例如在ORM 中,SQL WHERE 子句应该返回反集。
def __abs__(self):
return math.sqrt(sum(x * x for x in self))
def __neg__(self):
return Vector(-x for x in self) #为了计算 -v,构建一个新 Vector 实例,把 self 的每个分量都取反
def __pos__(self):
return Vector(self) #为了计算 +v,构建一个新 Vector 实例,传入 self 的各个分量
x 和 +x 何时不相等
每个人都觉得 x == +x,而且在 Python 中,几乎所有情况下都是这样。但是,我在标准库中找到两例 x != +x 的情况。
第一例与 decimal.Decimal 类有关。如果 x 是 Decimal 实例,在算术运算的上下文中创建,然后在不同的上下文中计算 +x,那么 x!= +x。例如,x 所在的上下文使用某个精度,而计算 +x 时,精度变了,例如下面的
❽ 运算符重载的方法
struct A
{
int a,b;
};
ostream &operator << (ostream &o,const A&aa)
{
o<<aa.a<<'\t'<<aa.b<<endl;
}
A &operator++(A &aa)
{
++aa.a,++aa.b;
return aa;
}
int main()
{
A a={1,2};
cout<<++a<<endl;
return 0;
}
这个只是一个最简单的重载的举例。。
❾ 如何重载运算符
我没编译。但是问题在于。你+=的是int。 int 对double, complex 都存在转换。它没法决定转换成哪个。所以你的main()中1改成1.0吧~
也可以为int再重载一遍。
❿ 如何实现函数运算符重载
3.运算符重载称动态多态性,他是通过继承和虚函数实现的。
运算符重载通过创建运算符函数operator@()来实现。运算符函数定义了重载的运算符将要进行的操作,这种操作通常作用在一个类上。这样,在编译时遇到名为operator@的运算符函数(@表示所要重载的运算符),就检查传递给函数的参数的类型。
重载运算符与预定义运算符的使用方法完全相同,它不能改变原有运算符的参数个数(单目或双目),也不能改变原有的优先级的结合性。用户不能定义新的运算符,只能从C++已有的运算符中选择一个恰当的运算符重载。
3.1成员运算符函数
运算符函数可以定义为它将要操作的类的成员(称为成员运算符函数),也可以定义为非类的成员,但是非成员的运算符函数大多是类的友元函数(称为友元运算符函数)。
成员运算符函数在类中的声明格式为:
class X{
//……
type operator@(参数表);
};
其中type为函数的返回类型,@为所要重载的运算符符号,X是重载此运算符的类名,参数表中罗列的是该运算符所需要的操作数。
成员运算符函数定义的形式一般为:
type X::operator@(参数表)
//函数体}
其符号的含义与声明时相同。
在成员运算符函数的参数表中,若运算符是单目的,则参数表为空,此时当前对象作为运算符的一个操作数,通过this指针隐含地传递给函数的;若运算符是双目的,则参数表中有一个操作数,它作为运算符的右操作参数,此时当前对象做为运算符的左操作数,它是this指针隐含地传递给函数的。总之成员运算符函数operator@所需要的一个操作数是由对象通过this指针隐含传递。