运算符及其重载
运算符
运算符实际就是函数
C++中的运算符有
+ - * / % ^ & | ~ ! = < > += -= *= /= %= ^= &= |= << >> >>= <<= == != <= >= <=> && || ++ -- , ->*
-> ( ) [ ]
运算符的重载
重载本质上是给运算符重新赋予新的含义
运算符的重载应该很少使用
举例
在不用运算符重载的情况下,我们可以这样相加两个向量,需要写个函数
#include <iostream>
struct Vector
{
float x, y;
Vector(float x, float y)
:x(x),y(y)
{}
Vector Add(const Vector& other)const
{
return Vector(x + other.x, y + other.y);
}};
int main()
{
Vector position(2.0f, 3.0f);
Vector speed(0.5f, 1.0f);
Vector result = position.Add(speed);
std::cout << result.x<<result.y << std::endl;
std::cin.get();}
重载+运算符
通过使用运算符重载我们可以修改代码如下
#include <iostream>
struct Vector
{
float x, y;
Vector(float x, float y)
:x(x),y(y)
{}
Vector Add(const Vector& other)const
{
return Vector(x + other.x, y + other.y);
}
Vector operator+ (const Vector& other)const
{
return Add(other);
}};
int main()
{
Vector position(2.0f, 3.0f);
Vector speed(0.5f, 1.0f);
Vector result = position+speed;
std::cout << result.x<<result.y << std::endl;
std::cin.get();}
重载<<运算符
我们也可以修改<<运算符,代码如下
#include <iostream>
struct Vector
{
float x, y;
Vector(float x, float y)
:x(x),y(y)
{}
Vector Add(const Vector& other)const
{
return Vector(x + other.x, y + other.y);
}
Vector operator+ (const Vector& other)const
{
return Add(other);
}};
std::ostream& operator<<(std::ostream& stream, const Vector other)
{
stream << other.x << other.y;
return stream;
}int main()
{
Vector position(2.0f, 3.0f);
Vector speed(0.5f, 1.0f);
Vector result = position+speed;
std::cout << result<< std::endl;
std::cin.get();}
重载运算符会降低代码可读性,所以尽量不要这样做
重载==运算符
result1和result2是两个实例化对象,不能通过==运算符比较,但我们可以重载==运算符
#include <iostream>
struct Vector
{
float x, y;
Vector(float x, float y)
:x(x),y(y)
{}
Vector Add(const Vector& other)const
{
return Vector(x + other.x, y + other.y);
}
Vector operator+ (const Vector& other)const
{
return Add(other);
}
bool operator==(const Vector& other)const
{
return x == other.x && y == other.y;
}};
std::ostream& operator<<(std::ostream& stream, const Vector other)
{
stream << other.x << other.y;
return stream;
}int main()
{
Vector position(2.0f, 3.0f);
Vector speed(0.5f, 1.0f);
Vector result1 = position.Add(speed);
Vector result2 = position+speed;
if (result1 == result2)
{}
std::cout << result1<< std::endl;
std::cin.get();}
补充
以下关于运算符及重载运算符有更为详细的解释
运算符重载 - cppreference.comhttps://en.cppreference.com/w/cpp/language/operators
this关键字
通过this可以访问成员函数,成员函数即属于某个类的函数或方法,在内部方法中我们可以引用this
this是一个指向当前对象实例的指针
举例
通过this调用类中当前方法外的变量
当我们在类中赋值时,可以采用成员初始化列表,代码如下
#include <iostream>
class Entity
{
public:
int x, y;
Entity(int x, int y)
:x(x),y(y)
{
}
};int main()
{
Entity e(1,2);
std::cin.get();}
但如果我想在函数内部写,类中的x变量和构造函数的x重复了 ,我们可以使用this关键字,this是一个指向当前对象实例的指针,修改代码如下
#include <iostream>
class Entity
{
public:
int x, y;
Entity(int x, int y)
{
(*this).x = x;
(*this).y = y;
}
};int main()
{
Entity e(1,2);
std::cin.get();}
在日常使用中我们通过->来代替
#include <iostream>
class Entity
{
public:
int x, y;
Entity(int x, int y)
{
this->x;
this->y;
}
};int main()
{
Entity e(1,2);
std::cin.get();}
通过this调用类以外的函数
因为this本质上是指针,而Printentity()需要传入实例化对象,所以要用*解引用
在类中用Printentity()所以要在void Printentity(const Entity& e);前做class Entity;的前置声明
#include <iostream>
class Entity;
void Printentity(const Entity& e);class Entity
{
public:
int x, y;
Entity(int x, int y)
{this->x;
this-> y;
Printentity(*this);
}
int Getx()const
{
return x;
}
};
void Printentity(const Entity& e)
{}
int main()
{
Entity e(1,2);
std::cin.get();}
对象的生存期(栈作用域生存期)
栈
栈可以认为是一种数据结构,可以在上面堆叠一些东西,就像桌子上的一堆书,你访问其中一本,需要把上面的先拿出来
一旦作用域结束,你把这本书拿出来,然后扔掉,你在书里写的基于栈的变量、所创造的对象就全消失了
举例
#include <iostream>
class Entity
{
private:
int x;
public:
Entity()
{
std::cout << "create entity" << std::endl;
}
~Entity()
{
std::cout << "destroy entity" << std::endl;
}};
int main()
{
{
Entity e;
}
std::cin.get();
}
结果
create entity
destroy entity
当将e在堆上创建,修改代码如下
#include <iostream>
class Entity
{
private:
int x;
public:
Entity()
{
std::cout << "create entity" << std::endl;
}
~Entity()
{
std::cout << "destroy entity" << std::endl;
}};
int main()
{
{
Entity* e=new Entity();
}
std::cin.get();
}
结果
create entity
所以在栈上创建一个变量,超出范围后,就会消失
作用域指针
利用栈内存的释放机制控制堆内存,而不用手动调用delete来释放内存,因为一旦超出作用域会自动调用delete释放内存
#include <iostream>
class Entity
{
private:
int x;
public:
Entity()
{
std::cout << "create entity" << std::endl;
}
~Entity()
{
std::cout << "destroy entity" << std::endl;
}
};class Scopedptr
{
private:
Entity* m_ptr;
public:
Scopedptr(Entity* ptr)
:m_ptr(ptr)
{
}
~Scopedptr()
{
delete m_ptr;
}
};int main()
{
{
Scopedptr e(new Entity());
}
std::cin.get();
}
结果
create entity
destroy entity
使用new关键字调用堆内存,结果得到调用栈内存一样的结果
此时Scopedptr对象e为栈上分配的,当自动消灭时调用析构函数 ~Scopedptr(),删除m_ptr,而m_ptr是堆上对象,被删除后自动调用~Entity()