运算符重载、构造析构、引用区别点和类信息识别

来源:互联网 发布:号码追逐软件 编辑:程序博客网 时间:2024/06/13 11:38

个人接触这方面有一段时间了,虽知道行浅,但还是愿意讲讲自己对这方面的理解。。也算自己为中国软件事业做点微不足道的小事吧。很多学习程序设计的,大部分都会很急躁,学着学着,越来越发现自己不会的东西越多,于是就否定自己。其实我想说,不管什么只要你认真,踏实就没有做不成的事。人要相信自己,虽说我们这行更新太快,但我们掌握了最核心的又怕什么呢。很多都是相通的。认真理解一个程序的来龙去脉,我觉得比看几本书还有意义。。。。好了,废话说多了,进入今天的主题。谈谈运算符重载、构造析构和引用的一点知识。

 

多于C++ 来说,一个类只有调用构造函数,才真正意义上分配了内存空间,而对于数据区是一个类私有的,函数接口是共用的。运算符重载不改变运算符的本质含义,只是扩展运算符的功能,我自己编写了一段代码,先上一段图:

定义一个类

class A
{
public:
 A(int = 0,int = 0,int = 10);  // 构造函数
 void Get();             // 数值打印函数
 A operator + (A &);    //  重载+运算符
 A& operator = (A &); // 重载=运算符
 const int* GetRuntimeClass()  // 标识类信息的地址信息
 {
  return &classCObject;        // 返回标识地址
 }
 ~A()                 // 析构函数
 {
  cout<<"析构函数!"<<" -->函数地址:"<<GetRuntimeClass()<<endl;endl;
  delete []Wei;    // 释放自己开辟的空间
 }
 
private:
 int x;
 int y;
 int Len;
 char*Wei;
 int classCObject;   // 标识类信息,数值我们不关心,只是该变量在类中的地址,并不是类的起始地址
};

这个类主要是为了测试一些基本运行信息设立的,希望对大家理解这方面有一定的帮助。

实现函数

 


A::A(int a,int b,int len)
{
 classCObject = len;   
 x = a;
 y = b;
 Wei = new char[len];    //  分配内存空间
 cout<<"构造函数!"<<"-->函数地址:"<<GetRuntimeClass()<<endl; // 打印出函数地址信息,方便观察类的内部运行机制
}

void A::Get()
{
 cout<<"x = "<<x<<"\ny = "<<y<<endl;
}
 // 此处如果返回类型变成引用,入A& A::operator + (A&a) 得不到想要的结果. 

A A::operator+(A&a)

     cout<<"我是加。"<<endl;
     return (A(x+a.x,y+a.y,10));  //构造出一个对象

}

A& A::operator = (A &a)
{
     x = a.x;
  y = a.y;
  Len = a.Len;
  cout<<"xx = "<<x<<"\nyy = "<<y<<endl;// 调试数值观察
  for(int i=0;i<Len;i++)
  {
        *(Wei+i) = *(a.Wei+i);   // 数值的拷贝,当然还可以用strcpy(Wei,a.Wei);
  }
    cout<<"我是赋值。"<<endl;
  return *this;       // 此处返回的是类的实例,因为其他标识符要做该类的别名
}
void main()
{
   A a(1,2,10),b(3,4,10),c;  // 定义对象
  // (a+b).Get();
   cout<<"a的地址"<<&a<<endl;
   c = a+b;  //  加法运算符重载,对象之间的浅拷贝
   c.Get();  //  输出c对象的私有数据的值
}

截图:

我们定义了3个对象首先就调用3次构造函数,屏幕打印出了3条构造函数信息,之后就执行a+b 调用重载函数,将a,b对象对应的参数相加后,就构造出一个对象,这就是为什么有
,执行完重载+后,就进行重载=运算符,屏幕打印xx = 4  yy = 6证明程序执行到此处,执行完重载=函数,+中构造出来的对象的生命周期结束,调用析构函数,将其析构掉,紧接着c.Get()函数 打印出数值,然后依次析构对象。
 
在这里值得我们注意的是,当重载运算符+中 如果返回的是一个引用,我们是得不到该对象的,因为,构造完以后马上就析构了。
函数没有得到具体的值,而打印的信息也说明,对象构造完以后,马上就析构了。很多问题我们看是简单,仔细观察都会有不同的结果。值得我们思考,这也就要求我们要对编译器比较了解了。
如果重载代码修改成

A& A::operator+(A&a)

     cout<<"我是加。"<<endl;
     return (A(x+a.x,y+a.y,10));  //构造出一个对象

}

是将构造出来的对象,临时对象作为其引用。但应该注意到的一点是,该对象马上就析构了。由于重载了=号运算符,所以得不到该对象。在没用重载=号的情况下,程序图片截图:

在重载了=号的情况下图片:

可以看到程序的值是随机值。我们可以想想,return语句究竟背着我们做了什么。感兴趣的可以自己百度下。

接下来我们谈谈编译器怎样运行语句:

A A::operator+(A&a)

     cout<<"我是加。"<<endl;
     return (A(x+a.x,y+a.y,10));  //构造出一个对象

}

首先我们构造出一个对象,然后将该对象返回给一个临时对象,这是一条语句。所以

编译器发现这两个对象是连续的同一个对象,所以没有必要再分配,编译器就通过计数器i记录引用的次数,通过图片程序:

本来构造出一个对象A(x+a.x,y+a.y,10),函数结束后本来要析构对象的,但由于编译器中计数器就减1,知道重载=号函数结束后,i再减1,对象析构。

希望通过本节的讲解,能够帮助到一些朋友更好的学习。不懂的可以留言,欢迎交流指正。。。 明天就是我生日了,没什么给自己的,祝自己开心快乐。。。。~~~~~~~~~~~~~~~~~~~~~~~~~~~~

代码的下载地址:http://download.csdn.net/detail/wu10045125/4767324