一.对象指针
1.什么叫对象指针
顾名思义就是指向对象的指针,如下图我们在堆上实例化一个对象时,使用指针*p指向我们实例化的对象,那么我们对对象数据的访问方法有两种。一种是常见的p->m_iX,另为一种就是(*p).m_iY.
思考能不能用指针指向在栈上实例化的对象呢?(肯定是可以的)具体实现如下图:
Coordinate p1;
Coordinate *p2 = &p1;
p2->m_iX = 10;
p2->m_iY = 20;
2.对象成员指针
对象指针的定义:如下图所示Line类中有两个数据成员为指针
其初始化有三种方式:初始化列表、普通初始化、用指针指向一个实例化的对象。最常用的是第三种方法。
3.对象成员与对象成员指针的区别:
如果是对象成员的话那么Line中有两个数据成员,上面可以看到一个数据成员包含m_iX和m_iY且都为int类型,在32位系统上sizeof(Line)总共包含4个int类数据占16个字节;但是对象成员指针呢,数据成员包含两个指针,在32位系统上一个指针4个字节,所以sizeof(Line)占8个字节;
4.代码实例
main函数文件
#include<iostream>
#include "Line.h"
Line::Line(int x1, int y1, int x2, int y2)
{
m_pCoorA = new Coordinate(x1, y1);
m_pCoorB = new Coordinate(x2, y2);
cout << "Line()" << endl;
}
Line::~Line()
{
delete m_pCoorA;
delete m_pCoorB;
m_pCoorA = NULL;
m_pCoorB = NULL;
cout << "~Line()" << endl;
}
//void Line::setA(int x, int y)
//{
// m_coorA.setX(x);
// m_coorA.setY(y);
//}
//
//void Line::setB(int x, int y)
//{
// m_coorB.setX(x);
// m_coorB.setY(y);
//}
void Line::printInfo()
{
cout << "(" << m_pCoorA->getX() << "," << m_pCoorA->getY() << ")" << endl;
cout << "(" << m_pCoorB->getX() << "," << m_pCoorB->getY() << ")" << endl;
}
Line.h和Line.cpp文件
#include<string>
#include"Coordinate.h"
using namespace std;
class Line
{
public:
Line(int x1,int y1,int x2,int y2 );
~Line();
//void setA(int x, int y);
//void setB(int x, int y);
void printInfo();
private:
Coordinate *m_pCoorA;
Coordinate *m_pCoorB;
};
#include<iostream>
#include "Line.h"
Line::Line(int x1, int y1, int x2, int y2)
{
m_pCoorA = new Coordinate(x1, y1);
m_pCoorB = new Coordinate(x2, y2);
cout << "Line()" << endl;
}
Line::~Line()
{
delete m_pCoorA;
delete m_pCoorB;
m_pCoorA = NULL;
m_pCoorB = NULL;
cout << "~Line()" << endl;
}
//void Line::setA(int x, int y)
//{
// m_coorA.setX(x);
// m_coorA.setY(y);
//}
//
//void Line::setB(int x, int y)
//{
// m_coorB.setX(x);
// m_coorB.setY(y);
//}
void Line::printInfo()
{
cout << "(" << m_pCoorA->getX() << "," << m_pCoorA->getY() << ")" << endl;
cout << "(" << m_pCoorB->getX() << "," << m_pCoorB->getY() << ")" << endl;
}
Coordinate.h和Coordiante.cpp文件
class Coordinate
{
public:
Coordinate(int x,int y);
~Coordinate();
//void setX(int x);
int getX();
//void setY(int y);
int getY();
public:
int m_iX;
int m_iY;
};
#include<iostream>
#include<stdlib.h>
#include<string>
#include "Coordinate.h"
using namespace std;
Coordinate::Coordinate(int x,int y)
{
m_iX = x;
m_iY = y;
cout << "Coordinate()" << m_iX <<","<< m_iY << endl;
}
Coordinate::~Coordinate()
{
cout << "~Coordinate" << m_iX << "," << m_iY << endl;
}
//void Coordinate::setX(int x)
//{
// m_iX = x;
//}
int Coordinate::getX()
{
return m_iX;
}
/*void Coordinate::setY(int y)
{
m_iY = y;
}
*/
int Coordinate::getY()
{
return m_iY;
}
运行结果显示:首先对象实例化和销毁的顺序和对象成员一样,然后我们看到打印的结果也和我们上面说的一样,一个指针占4个字节,Line占8个字节。
二、this指针
1.this指针
如果参数与数数据成员同名会怎么样呢?
我们迫切需要一种技术要么可以标记出参数要么可以标记出数据成员!如下图所示this指针当我们实例化arr1时this指针指向arr1的地址,实例化arr2时指向arr2的地址,这样就可以分清楚数据成员和传递的参数了!不过大家放心this指针是编译器给我们加上去的,并不需要我们自己加!
2.this指针的应用
a.清晰地识别数据成员和要传递的参数
b.可以实现一些功能
通过下面的代码,我们可以发现我们让printInfo函数的返回类型变成了Array&,即引用。然后就可以使用arr1.printInfo().setLen(5);
这样的连点语句直接调用后面的set函数。这就是this的应用之一了,因为此时的this指针指向的是arr1的地址,所以可以顺利的调用arr1的函数了!
main函数文件:
#include<iostream>
#include<stdlib.h>
#include<string>
#include "Array.h"
using namespace std;
/****************************************************************/
/*
示例要求:
定义一个Array类。
数据成员:m_iLen表示数组长度
成员函数:
构造函数
析构函数
len的封装函数
信息输出函数printInfo
*/
/****************************************************************/
int main(void)
{
Array arr1(10);
arr1.printInfo().setLen(5);
cout << "len=" << arr1.getLen() << endl;
system("pause");
return 0;
}
Array.h和Array.cpp文件:
class Array
{
public:
Array(int len);
~Array();
void setLen(int len);
int getLen();
Array& printInfo();
private:
int len;
};
#include "Array.h"
#include<iostream>
using namespace std;
Array::Array(int len)
{
this->len = len;
}
Array::~Array()
{
}
void Array::setLen(int len)
{
this->len = len;
}
int Array::getLen()
{
return len;
}
Array& Array::printInfo()
{
cout << "len=" << len << endl;
return *this;
}
c.当然我们也可以把printInfo的返回类型变成Array*,同时也改造一下我们的set函数让它也返回this指针。
mian函数文件:
#include<iostream>
#include<stdlib.h>
#include<string>
#include "Array.h"
using namespace std;
/****************************************************************/
/*
示例要求:
定义一个Array类。
数据成员:m_iLen表示数组长度
成员函数:
构造函数
析构函数
len的封装函数
信息输出函数printInfo
*/
/****************************************************************/
int main(void)
{
Array arr1(10);
arr1.printInfo()->setLen(5)->printInfo();
system("pause");
return 0;
}
Array.h和Array.cpp文件:
class Array
{
public:
Array(int len);
~Array();
Array* setLen(int len);
int getLen();
Array* printInfo();
private:
int len;
};
#include "Array.h"
#include<iostream>
using namespace std;
Array::Array(int len)
{
this->len = len;
}
Array::~Array()
{
}
Array* Array::setLen(int len)
{
this->len = len;
return this;
}
int Array::getLen()
{
return len;
}
Array* Array::printInfo()
{
cout << "len=" << len << endl;
return this;
}
c和b运行结果相同且为:
d.最后我们来验证一下this指针和我们实例化的对象地址是不是相同的
代码我们就上面c的进行一点改动就好:
int main(void)
{
Array arr1(10);
arr1.printInfo();
cout << &arr1 << endl;
system("pause");
return 0;
}
Array* Array::printInfo()
{
cout << this << endl;
return this;
}
结果显示:两个的地址的确相同!