c++中 struct 和 class 特性几乎一模一样
所以很多都是共有的特性 篇幅就很多了
c++中 我觉得最牛皮的概念之一 就是
重载运算符 operator 关键字
这个东西 能将 我们的 运算符 (+-*/) new delete
类型转换
写在类里面当成员函数 并制定 该类型变量运算时所适用的逻辑
以下是可重载的所有运算符:
这是重载运算符时的方式 注意 运算符替换掉 @
运算符 前缀后缀 放置位
限制 或 不可重载的符号
struct obj_3
{
obj_3() {};
obj_3(const int& Ina, const int& Inb) : a(Ina), b(Inb) {}
int geta()const { return a; };
int getb()const { return b; };
private:
int a = 0;
int b = 0;
};
struct obj_1
{
public:
obj_1() { Ts = this; };
//使用了委托构造
obj_1(const int& Ina, const int& Inb) : obj_1() { a = Ina; b = Inb; }
int geta() const { return a; };
int getb() const { return b; };
public:
bool operator== (const obj_1& Target)
{
return (this->a == Target.a) && (this->b == Target.b);
};
bool operator!= (const obj_1& Target)
{
return !operator==(Target);
};
operator obj_3()
{
std::cout << __func__ << ":" << endl;
return obj_3(99, 99);
}
void* operator new(std::size_t size, void* p, int io,char* c)
{
std::cout << "obj_1::" << __func__ << "(std::size_t size, void* p,char* c) :" << endl;
std::cout << "operator new 构造的地址是:" << p << endl;
std::cout << "operator new io :" << io << endl;
std::cout << "operator new c :" << c << endl;
return p;
}
void operator delete(void* p,size_t size, const char* c)
{
std::cout << "obj_1::" << __func__ << "(void* p,size_t size, const char* c) :" << endl;
std::cout << "operator delete的地址是:" << p << endl;
std::cout << "operator delete size :" << size << endl;
std::cout << "operator delete c :" << c << endl;
return;
}
int operator[](int i)
{
std::cout << "obj_1::" << __func__ << "(int i) :" << endl;
std::cout << "i = "<< i << endl;
return a + i;
}
~obj_1() {};
private:
obj_1* Ts;
int a = 0;
int b = 0;
};
struct obj_2
{
obj_2() {};
obj_2(const int& Ina, const int& Inb) : a(Ina), b(Inb) {}
int geta()const { return a; };
int getb()const { return b; };
obj_2& operator= (const obj_1& Target)
{
std::cout << "obj_2::" << __func__ << "(const obj_1& Target) :" << endl;
this->a = Target.geta();
this->b = Target.getb();
return *this;
};
operator obj_1()
{
std::cout << "obj_2::" << __func__ << ":" << endl;
return obj_1(this->a, 100);
}
~obj_2() {};
private:
int a = 0;
int b = 0;
};
int main()
{
std::cout << __func__ <<":"<< endl;
obj_1 a1(10, 1000);
obj_2 b2(50, 10);
obj_3 c3;
obj_1 texta1;
obj_2 textb2;
std::cout << "初始化完各个对象的值" << endl;
std::cout << "a1.a: "<<a1.geta() << endl;
std::cout << "a1.b: " << a1.getb() << endl;
std::cout << "b2.a: " << b2.geta() << endl;
std::cout << "b2.b: " << b2.getb() << endl;
std::cout << "c3.a: " << c3.geta() << endl;
std::cout << "c3.b: " << c3.getb() << endl;
std::cout << "texta1.a: " << texta1.geta() << endl;
std::cout << "texta1.b: " << texta1.getb() << endl;
std::cout << "textb2.a: " << textb2.geta() << endl;
std::cout << "textb2.b: " << textb2.getb() << endl;
textb2 = a1;
std::cout << "该操作完成时各个变量的值" << endl;
std::cout << "a1.a: " << a1.geta() << endl;
std::cout << "a1.b: " << a1.getb() << endl;
std::cout << "textb2.a: " << textb2.geta() << endl;
std::cout << "textb2.b: " << textb2.getb() << endl;
texta1 = (obj_1)b2;
std::cout << "该操作完成时各个变量的值" << endl;
std::cout << "b2.a: " << b2.geta() << endl;
std::cout << "b2.b: " << b2.getb() << endl;
std::cout << "texta1.a: " << texta1.geta() << endl;
std::cout << "texta1.b: " << texta1.getb() << endl;
c3 = a1;
std::cout << "该操作完成时各个变量的值" << endl;
std::cout << "a1.a: " << a1.geta() << endl;
std::cout << "a1.b: " << a1.getb() << endl;
std::cout << "c3.a: " << c3.geta() << endl;
std::cout << "c3.b: " << c3.getb() << endl;
std::cout << "a1[100]: " << a1[100] << endl;
static char b[10] = { 0 };
char p = '2';
obj_1* pobj1 = ::new obj_1;
obj_1* pobjw = new(b, 9000,&p) obj_1;
::delete pobj1;
obj_1::operator delete( pobjw,60,&p);
return 0;
}
部分测试代码我已放上
接下来我们运行看看
好 我们先看看第一处
textb2 = a1;
textb2 是obj_2类型 a1 是obj_1类型
本来两个互不相同的自定义类型是无法使用 = 运算符的
但是此刻可以了 为何讷
就因为运算符重载 operator
我们找到 obj_2 结构体是如何定义的
我们发现 有个
obj_2& operator= (const obj_1& Target) 函数
其中有个输出函数 我们继续来看控制台
obj_2::operator =(const obj_1& Target) :
证明 textb2 = a1;
的确是运行了此函数
所以 obj_2& operator= (const obj_1& Target)
这个叫什么?
这个叫重载赋值符号
Target引用的值其实就是 a1
这是类中的写法
具体详细的大家去打断点试试
------------------------------------------------------------------------------
接下来看看这个
texta1 = (obj_1)b2;
texta1 是obj_1类型 b2 是obj_2类型
这语句一看 类型转换
但是细看 不对劲 不相关类型 如何支持转换
看了下控制台 输出了obj_2::operator struct obj_1:
我们去找找 obj_2里 输出的地方
operator obj_1()
这是什么?
这叫类型转换函数
obj_2 里面有个这个 证明了 有转换到 obj_1类型的方法
它返回了一个obj_1的临时对象
我们看看a 和 b
b2.a: 50
b2.b: 10
texta1.a: 50
texta1.b: 100
构造的临时对象中的a使用了 b2.a , b使用了 100
看了 没错是正确的
还是不太懂?
没事 继续看看
c3 = a1;
obj_3类型 c3 obj_1类型 a1;
这题一看 哎呦 我会 刚刚学过的 重载赋值运算符嘛!
一看输出 不对劲 operator struct obj_3:
怎么是类型转换函数呢?
去 obj_3类中看看
发现并没有operator 的函数
那就去obj_1类中看看
operator obj_3()
发现了obj_3 类型转换函数
所以这题运行的是类型转换函数
--------------------------------------------------------------------
接下来我们看
a1[100]
这个不是数组写法吗?
a1不是 obj_1类型的对象吗?
如何能当数组用 它又输出何物?
我们去看看obj_1类中怎么写的
我们发现了 int operator[](int i)
看见了什么 operator 关键字 又是重载运算符
这次原来是重载数组运算符
返回的是 return a + i;
看了下 输出是 110
之前a1.a 是多少?
-----------------------------------------------------------------
接下来我们来看看
void* operator new
重载 new 与 delete
直呼woc c++ 还有什么运算符不能重载
void* operator new(std::size_t size, void* p, int io,char* c)
当然重载new 有一定的要求:
第一个形参必须是 size_t 类型的参数
看编译报错了
一般何时我们需要重载new呢?
要在指定的空间上进行创建对象时会进行重载
比如这里
我们看到了一个
obj_1* pobjw = new(b, 9000,&p) obj_1;
这写法很怪异
我们注意到了
b 是一个数组变量 证明是个地址
new(b, 9000,&p) 而语句是如此
我们去看看 重载位置 obj_1类中
看到了形参顺序 std::size_t size, void* p, int io,char* c
而调用是 new(b, 9000,&p) obj_1
有输出语句 我们去看看
我们发现 b= 00007FF6B74C0E90 io = 9000 c = ’2‘
顺序是按照 new(b, 9000,&p) obj_1
至于delete 要求是 第一个形参必须为 void *
浅谈结束
大家可以去该网站看看特性 语法规则
https://zh.cppreference.com/w/cpp/language/operators