精华内容
下载资源
问答
  • c++中 运算符重载 const 函数

    千次阅读 2018-11-10 14:57:10
    本篇文章主要内容是关于运算符重载,然后在最后提了一下 const修饰函数时的状况。后面会补上一个日期类的定义。 文章目录概要赋值运算符的重载= 号的重载i++ 和 ++i 前置与后置++的区别const 修饰函数 赋值运算符的...

    概要

    本篇文章主要内容是关于运算符重载,然后在最后提了一下 const修饰函数时的状况。后面会补上一个日期类的定义。

    赋值运算符的重载

    函数可以重载,在 C++ 中可以使用赋值运算符的重载。
    函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
    函数名字为:关键字operator后面接需要重载的运算符符号。
    函数原型:返回值类型 operator操作符(参数列表)

    在c++中只有 .* :: sizeof ? : . 不能重载。

        #include<iostream>
        #include<Windows.h>
        using namespace std;
        
        class Day
        {
        private:
        	int _year;
        	int _month;
        	int _day;
        public:
        	Day(int year = 2018, int month = 10, int day = 30);
        	friend bool operator == (const Day &d1,const Day &d2);
        };
        	Day::Day(int year , int month , int day )
        {
        	_year = year;
        	_month = month;
        	_day = day;
        }
        bool operator == (const Day &d1,const Day &d2)
        {
        	if ((d1._year == d2._year) && (d1._month == d2._month) && (d1._day == d2._day))
        	{
        		return true;
        	}
        	return false;
        }  
        int main()
        {
        	
        	Day d1(2018, 11, 14);
        	Day d2(2018, 12, 14);
    		if(d1 == d2)
    	//	if(operator (d1,d2))
    	{
    		printf("d1 == d2");
    	}
    		else
    	{
    		printf("d1 != d2");
    	}
        	system("pause");
        	return 0;
        }
    

    以上代码使用了运算符重载。这里的运算符重载是使用了友元声明 friend。由于运算符需要权限对对象中的变量进行操作,所以运算符重载函数需要全局操作。

    运算符重载也可以放在类中,不过值得注意的是类中的运算符重载要考虑this 指针问题。

    	class Day
    	{
    	public:
    		bool operator == (const day &d1)
    		{
    			if ((this->_year == d1._year) && (this->_month == d1._month) && (this->._day == d1._day))
        	{
        		return true;
        	}
        	return false;
    	}
    

    运算符重载的目的,让编译器支持自定义类型一些相应运算符的操作。为什么要引入运算符重载?是为了提供代码的可读性。这里要区分函数重载和运算符重载。

    注意:运算符重载必须是自定义类型,如果有以下的重载是错误的。

    int operator + (int left,int right);

    重载不可以是内置类型的。

    Date operator + (Date left)

    • 符号是双目运算符不可以在参数列表当中只写一个参数。

    Date operator @ (Date left, Date right)

    @ 符号在 c++当中不是操作符,所以不能进行重载。

    = 号的重载

        void Day:: operator = (const Day &d)
    	//这个函数重载不能连续赋值不符合输入习惯。
        {
        	_year = d._year;
        	_month = d._month;
        	_day = d._day;
        }
    	
        	Day& Day:: operator = ( Day &d)
        //这个函数重载不安全可能会修改被复制的变量。
    	//并且不能把连续 = 号的最左边的赋值给最右边的。 
    	//(a = b = c) == (1. b = c 2. a = b)
    	//赋值是有顺序的
        {
        	_year = d._year;
        	_month = d._month;
        	_day = d._day;
        	return d;
        }
    	
        	Day Day:: operator = (const Day &d)
        //这个函数重载是合理的 temp 作为参数传给下一个变量。
        {
        	_year = d._year;
        	_month = d._month;
        	_day = d._day;
        	Day temp(*this);
    		return temp;
        }
    

    i++ 和 ++i 前置与后置++的区别

        Day operator ++(Day &d, int)
        {
        	Day temp = d;
        	d._day++;
        	return temp;
        }
        Day &operator ++(Day &d)
        {
        	d._day++;
        	return d;
        }
    

    前置 ++ 的返回值是 加1后的结果,它的运算符重载是没有多余参数的,除了this执政没有别的参数。 后置 ++需要将加之前的参数保存起来。然后再自加,自加结束后返回之前保存的值。后置++ 的参数列表多了一个 int ,这个int并没有实际的含义,它只是区别前置和后置的标志。

    const 修饰函数

    const类型不但可以修饰成员变量 ,还可以修饰成员函数。

        #include <iostream>
        using namespace std;
        class Test
        {
        private:
        	int _t;
        	// mutable int _a;
        public:
        	Test(int t)
        	{
        		_t = t;
        	}
        	void SetParam(int t)
        	{
        		_t = t;
        	}
        	int GetParam()const 
        	{
        		return _t;
        	}
        };
        int main()
        {
        	Test t1(10);
        	t1.SetParam(20);
        	const Test t2(10);
        	t2.SetParam(20);//报错
        	t2.GetParam();
        	return 0;
        }
    

    如果创建了一个 const 类型的对象,那么它的this指针也会随之改变。

    const Test t2(20) --> const Test* const this

    这种改变的后果就是被const变量修饰的成员变量不能被普通成员函数所使用。
    因为它的 this 指针不同。const修饰的是this 所指向的空间内容,这个内容是具有常属性的不可被改变。

    如果想要让被修改,可以使用 mutable 指出,即使成员函数或者类变量为const,其某个成员也可以被修改。

    在c++的类中, 如果一个成员函数被const 修饰,那么它将无法修改其成员变量的,但是如果这个成员变量是被mutable修饰的话,则可以修改。

    展开全文
  • 运算符重载 const friend

    千次阅读 2014-07-09 19:40:16
    6、起初不明白运算符重载,以为第一种声明只适合于vector*scalar的情形,而不适合scalar*vector的情形。实际上,两者都可以。 7、而对于下面的重载定义,要注意形参的顺序。第一个定义中,第一个形参是对象本身,...

    Coder 真的需要自己动手去写代码,而不是仅仅看懂了规则就行的

    今天试着写个复杂点的程序,刚开始的一个结构体就就遇到了好多问题。



    就拿这个来说吧。

    1、首先说运算符重载,形式只有两种:重载为的成员函数 or 重载为类的友元函数。基本数据类型是不需要也无法进行运算符重载的,很简单的道理,我却没想到。

    2、接下来上面的x,y,z肯定是类里面的数据成员啦,对应的是 重载为类的成员函数。这种重载的格式是:函数类型 operator 运算符(形参表) {}。

    3、下面一种重载形式就是重载为类的友元函数。有2个参数,而重载为类的成员函数只有一个参数,因为另一个参数就是该对象本身。

    4、const 修饰变量:对于其他变量没什么说的,对于指针,则可以分为2种:顶层const,常量指针,表示指针本身是个常量;底层const,指向常量的指针,表示所指的对象是个常量。区分:从右向左阅读。

    5、const 修饰函数:表示成员函数不会修改类的成员。所以不要在第二个重载函数后面加上const,否则会出现“非成员函数上不允许使用类型限定符”的错误。

    6、起初不明白运算符重载,以为第一种声明只适合于vector*scalar的情形,而不适合scalar*vector的情形。实际上,两者都可以。

    7、而对于下面的重载定义,要注意形参的顺序。第一个定义中,第一个形参是对象本身,省略没写,第二个参数才是scalar;而若将第二个定义的形参位置对调后,两个定义就相同了,出现这个错误。


    展开全文
  • 问题 在刷题的时候经常会遇到需要自己写...在重载比较函数的时候有些疑惑于哪里需要加const,所以今天总结一下。 看下面的简单例子: struct Student{ int ID; bool operator<(const Student &student...

    问题

    在刷题的时候经常会遇到需要自己写结构体并且自己重载比较函数的情况,特别是有时候需要用一些STL容器(如priority_queue)储存结构体的时候。在重载比较函数的时候有些疑惑于哪里需要加const,所以今天总结一下。
    看下面的简单例子:

    struct Student{
        int ID;
        bool operator<(const Student &student) {
            return ID < student.ID;
        }
        Student(int id): ID(id){}
    };
    
    int main() {
        cout << (Student(111) < Student(222)) << endl;
        return 0;
    }
    

    输出结果是1也就是true。但是当我们更改main函数时:

    int main() {
        priority_queue<Student> q;
        q.push(Student(111));
        return 0;
    }
    

    此时会报错:
    在这里插入图片描述
    当我们更改运算符重载函数为如下后可以顺利运行

    struct Student{
        int ID;
        bool operator<(const Student &student) const{
            return ID < student.ID;
        }
        Student(int id): ID(id){}
    };
    int main() {
        priority_queue<Student> q;
        q.push(Student(111));
        return 0;
    }
    

    可以看出,当我们将重载函数改为const函数时即可顺利运行。分析报错信息以及简单查询STL底层代码可以看出,当priority_queue在调用我们所写的重载比较函数时,输入的参数为const的student对象。只有const成员函数才能访问const对象中的数据,而非const成员函数不能。所以才会出现上述错误。

    总结

    在使用STL容器如priority_queue等储存结构体时,如果需要重载比较函数且STL容器需要调用该比较函数时,要将比较函数写为const函数。即如下写法:bool operator<(const T &t) const {}

    展开全文
  • 说明重载引入语法格式友元重载成员重载对比赋值运算符重载const 修饰返值 说明 从这篇博客开始,我会用连续的几篇博客对于C++运算符重载进行详细说明。 对于基本数据类型,比如 int 类型,我们对其进行加、减、乘、...

    运算符重载本质

    运算符重载的本质是函数重载。
    函数名是 operator x(后面的x表示重载运算符)

    说明

    对于基本数据类型,比如 int 类型,我们对其进行加、减、乘、除运算,是语言层面己经设置好的。但是对于结构类型,比如 struct Complex 类型的对象是否也可以直接进行加、减、乘、除运算呢,答案是否定的。

    要想实现自定义类型加、减、乘、除运算,怎么操作呢,对加、减、乘、除运算符进行重载,也就是本博客要说明的内容。

    重载引入

    语法格式

    重载运算符函数的一般格式如下,operator 是关键字 ,后面跟需要重载的运算符。==operator+==运算符构成了新的函数名,此时我们说 + 运算符被重载了。

    返值类型  operator 运算符名称(形参列表)
    {
    		函数实体;
    }
    

    友元运算符重载

    我们在说明友元的时候已经说明过友元函数重载,那么在这里我们直接使用。

    通过友元的方式实现了运算符重载达到Comlpex类生成的对象相加的目的。

    #include <iostream>
    using namespace std;
    
    class Comlpex
    {
    	//友元重载
    	friend Comlpex operator+(Comlpex& c1, Comlpex& c2);  
    public:
    	Comlpex(double r = 0, double i = 0) //构造器
    	:real(r), image(i) 
    	{}	
    
    	void dumpFormat()//类内普通成员函数实现
    	{
    		cout << "(" << this->real 
    		<< "," << this->image << ")"<<endl;
    	}
    
    private:
    	double real;
    	double image;
    };
    
    // + 运算符重载
    Comlpex operator+(Comlpex & c1, Comlpex & c2)	
    {
    	Comlpex c;
    	c.real = c1.real + c2.real;
    	c.image = c1.image + c2.image;
    	return c;
    }
    
    int main()
    {
    	Comlpex c1(3, 4);
    	c1.dumpFormat();
    	Comlpex c2(5, 6);
    	c2.dumpFormat();
    	Comlpex sum = c1 + c2;   // Comlpex sum = operator+(c1,c2);
    	sum.dumpFormat();
    	return 0;
    }
    

    运行结果为:

    运行结果

    通过友元的方式实现了Comlpex生成对象相加。

    我们知道基础类型向加减的时候我们就不需要运算符重载,例如:

    int a;
    int b;
    int c = a + b;
    

    但凡涉及到自定义类型想要跟普通数据类型一样的操作体验,就需要实现运算符重载。

    简单理解:上面实现友元重载就是一个全局函数实现运算符重载。

    成员运算符重载

    友元运算符重载到成员运算符重载,少了一个参数。
    少的参数,即左操作数,也就是类内成员函数中默认的this 指针。

    #include <iostream>
    using namespace std;
    
    class Comlpex
    {
    public:
    	Comlpex(double r = 0, double i = 0) //构造器
    	:real(r), image(i)
    	 {}
    
    	void dumpFormat()	//类内成员函数
    	{
    		cout << "(" << this->real << "," 
    		<< this->image << ")"<<endl;
    	}
    	
    	//类内实现 + 运算符重载
    	Comlpex operator+(const Comlpex & another)	
    	{
    		Comlpex c;
    		c.real = this->real + another.real;
    		c.image = this->image + another.image;
    		return c;
    	}
    
    private:
    	double real;
    	double image;
    };
    
    int main()
    {
    	Comlpex c1(3, 4);
    	c1.dumpFormat();
    	Comlpex c2(5, 6);
    	c2.dumpFormat();
    	Comlpex s = c1 + c2;
    	Comlpex s1 = c1.operator+(c2);
    	s.dumpFormat();
    	s1.dumpFormat();
    	return 0;
    }
    

    运行结果为;
    运行结果

    我们在计算的时候并不会改变对象的内容,所以在对于对象进行传参的时候也需要加上const。

    局部变量不能返回引用。
    栈上的对象可以返回,栈上的引用不可以返回。

    对比赋值运算符重载 =

    我们来对比之前赋值运算符重载的实现:

    #include <iostream>
    using namespace std;
    
    class Comlpex
    {
    public:
    	Comlpex(double r = 0, double i = 0) //构造器
    	:real(r), image(i) 
    	{}
    
    	void dumpFormat()		//类内成员函数实现
    	{
    		cout << "(" << this->real 
    		<< "," << this->image << ")"<<endl;
    	}
    
    	Comlpex & operator=(const Comlpex & another) // = 运算符重载
    	{
    		this->real  = another.real;
    		this->image =  another.image;
    		return  *this;
    	}
    
    private:
    	double real;
    	double image;
    };
    
    int main()
    {
    	Comlpex c1(3, 4);
    	Comlpex c2(5, 6);
    	c2 = c1;
    	c1.dumpFormat();
    	c2.dumpFormat();
    	return 0;
    }
    

    运算结果为:
    运行结果

    在我们的基本类型中可以有以下写法:

    int x,y,z;
    x = y = z;
    (x = y) = z;
    

    对于+运算符

    x+y+z;
    x+(y+z);
    (x+y)+z;
    

    上面都没有问题。
    但是

    (x+y) = z;
    

    就会出现问题。
    那么对于我们上面创建的对象

    (x+y) = z;
    

    是可以实现的:

    Comlpex operator+(Comlpex & another)
    	{
    		Comlpex c;
    		c.real = this->real + another.real;
    		c.image = +this->image + another.image;
    		return c;
    	}
    

    那么就出现了问题:运算符重载的实现和基础类型规则相违背,我们就要进行修改必须符合基本类型运算规则。

    返回c的时候并没有主函数去进行接收,那么就会返回在main函数的匿名对象,那么对象x+y就是一个匿名对象,匿名对象被赋值为s。我们知道给匿名对象进行赋值之后匿名对象最终会消失。那么就没有什么实际的意义了,所以为了解释这个问题我们在前面加上const:

    const Comlpex operator+(Comlpex & another)
    {
    	Comlpex c;
    	c.real = this->real + another.real;
    	c.image = +this->image + another.image;
    	return c;
    }
    

    这个时候

    (x+y) = z;
    

    就会直接报错。

    通过上面理解那么我们对于代码整体进行修改后为:

    #include <iostream>
    using namespace std;
    
    class Complex
    {
    	friend const Complex operator+(const Complex &c1,
    	const Complex &c2);
    
    public:
    	Complex(float x=0, float y=0)	//构造器
    	:_x(x),_y(y)
    	{}
    
    	void dis()	//类内普通成员函数
    	{
    		cout<<"("<<_x<<","<<_y<<")"<<endl;
    	}
    	
    	//+ 运算符重载声明
    	Complex const operator+(const Complex &another);
    
    private:
    	float _x;
    	float _y;
    };
    
    //+ 运算符重载全局函数实现
    const Complex operator+(const Complex &c1,const Complex &c2)
    {
         cout<<"friend overload"<<endl;
         return Complex(c1._x + c2._x,c1._y + c2._y);
    }
    
    //+ 运算符重载成员函数实现
    const Complex Complex::operator+(const Complex & another)
    {
    	cout<<"func member overload"<<endl;
    	return Complex(this->_x + another._x,this->_y + another._y);
    }
    
    int main()
    {
    	Complex c1(2,3);
    	Complex c2(3,4);
    	c1.dis();
    	c2.dis();
    	// Complex c3 = c1+c2;
    	// Complex c3 = operator+(c1,c2);
    	Complex c3 = c1+c2; 
    	c3.dis();
    	return 0;
    }
    

    运行结果为:

    运算结果
    所以我们之后就要在代码编写完成之后考虑是否需要加上const。

    const 修饰返回值

    C++引入引用的概念后,表达式可以被赋值的现象就出现了,有的表达式可以被赋值,有的表达式则不可以。

    比如,int a; int b; int c; (a=b)= c; 是可以的。而,(a+b) =c ;则是不允许的。

    重载的运算符是否会导致表达式可以被赋值应该以基础类型为准。
    返回类型通过加 const 加以限定来实现。
    并不是所有的表达式均可被赋值。

    表达式能被赋值的原因:
    返回引用可以被赋值,返回匿名对象可以被赋值。

    被const修改的对象不能赋值。

    展开全文
  • 类的默认成员函数 ...3、取地址运算符重载,包含取地址运算符重载const取地址运算符重载。 1、构造函数 1.1、构造函数概念 构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调...
  • 文章目录1.[]运算符重载2.+运算符重载3.+=运算符重载4.<<运算符重载,插入运算符5.>>运算符重载,提取运算符 1.[]运算符重载const版本和非const版本(nonconst) 要以非const版本调用const版本,避免...
  • 【C++】运算符重载关于const的分析(超详细)

    千次阅读 多人点赞 2020-02-23 20:24:56
    C++运算符重载重载运算符“+”第1个const第2个const第3个const重载运算符“-”重载运算符“-”(与上面的含义不同)重载运算符 “+=” 与 “-=”重载运算符 “==” 与 “!=”重载运算符 “++” 与 “--”重载 “<...
  • 1.运算符重载 C++为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数,也具有其返回值类 型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。 一个复制运算符重载的例子:...
  • []运算符重载 +运算符重载 +=运算符重载 >>运算符重载 例子代码: #include #include using namespace std; class String { public: String(const char* str=""); String(const String& other); Strin
  • C++为了增强代码的可读性引入了运算符重载运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。 函数名字:关键字operator后面接需要重载的...
  • 文章目录一、运算符重载二、复数类CComplex三、输出运算符重载 一、运算符重载 运算符重载: 使对象的运算运算表现得和编译器内置类型一样,使同一个运算符可以有不同的功能。即定义一个重载运算符的函数,使指定的...
  • 一、运算符重载基本概念 二、运算符重载碰上友元函数 三、可重载的运算符 四、自增自减(++/--)运算符重载 五、赋值(=)运算符重载 六、等于和不等于(==、!=)运算符重载 七、不要重载&&、|| 八、符号...
  • c++运算符重载

    2020-12-31 15:20:13
    运算符重载 const成员函数重载
  • 一、++运算符重载 前置++运算符重载 成员函数的方式重载,原型为: 函数类型 & operator++(); 友元函数的方式重载,原型为: friend 函数类型 & operator++(类类型 &); 后置++运算符重载 成员函数的方式重载,原型...
  • 一、运算符重载扩展C++中提供的运算符适用范围,以用于类所表示的抽象数据类型运算符重载实质是函数重载运算符重载是成员函数时,a+b的 a.operator+b,a 相当于对象,只传入后面的参数class A { public: A(double r...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 71,766
精华内容 28,706
关键字:

运算符重载const