C++ 类对象和 指针的区别html
转自:http://blog.csdn.net/ym19860303/article/details/8557746程序员
指针的状况数组
class Test{ public: int a; Test(){ a = 1; } }; int main() { Test* t1 = new Test(); t1->a = 10; Test* t2 = new Test(); t2->a = 5; cout << "&t1:" << t1 << " a = " << t1->a << endl; cout << "&t2:" << t2 << " a = " << t2->a <<endl; cout << "------------------------------" << endl; t2 = t1; cout << "&t1:" << t1 << " a = " << t1->a << endl; cout << "&t2:" << t2 << " a = " << t2->a <<endl; cout << "------------------------------" << endl; t1->a = 111; t2->a = 222; cout << "&t1:" << t1 << " a = " << t1->a << endl; cout << "&t2:" << t2 << " a = " << t2->a <<endl; return 0; }
对象的状况:app
class Test{ public: int a; Test(){ a = 1; } }; int main() { Test t1; t1.a = 10; Test t2; t2.a = 5; cout << "&t1:" << &t1 << " a = " << t1.a << endl; cout << "&t2:" << &t2 << " a = " << t2.a <<endl; cout << "------------------------------" << endl; t2 = t1; cout << "&t1:" << &t1 << " a = " << t1.a << endl; cout << "&t2:" << &t2 << " a = " << t2.a <<endl; cout << "------------------------------" << endl; t1.a = 111; t2.a = 222; cout << "&t1:" << &t1 << " a = " << t1.a << endl; cout << "&t2:" << &t2 << " a = " << t2.a <<endl; return 0; }
类的对象和类的指针的区别ide
转自:http://blog.csdn.net/neuqbingoye/article/details/7184090函数
class Student { public: static int number; string name; public: Student() { } void print() // 态成员函数 print() { std::cout < < name < <" : The number of the students is " < < number < < " numbers." < < std::endl; // 调用静态数据成员 } };
类对象:Student s1 类指针:Student *s2工具
很关键的一点:定义对象实例时,分配了内存,指针变量则未分配类对象所需内存。post
类的指针:他是一个内存地址值,他指向内存中存放的类对象(包括一些成员变量所赋的值).
对象,他是利用类的构造函数在内存中分配一块内存(包括一些成员变量所赋的值). url
指针变量是间接访问,但可实现多态(经过父类指针可调用子类对象),而且没有调用构造函数。
直接声明可直接访问,但不能实现多态,声明即调用了构造函数(已分配了内存)。
类的对象:用的是内存栈,是个局部的临时变量.
类的指针:用的是内存堆,是个永久变量,除非你释放它.
1.在类的声明还没有完成的状况下,能够声明指向该类的指针,可是不可声明该类的对象... 例如:含有纯虚成员函数的抽象类。
2.父类的指针能够指向子类的对象..
在应用时:
1.引用成员: 对象用" . "操做符; 指针用" -> "操做符.
2.生命期: 如果成员变量,则是类的析构函数来释放空间;如果函数中的临时变量,则做用域是该函数体内.而指针,则需利用delete 在相应的地方释放分配的内存块.
注意:用new ,必定要delete..
C++的精髓之一就是多态性,只有指针或者引用能够达到多态。对象不行
类指针的优势:
第一实现多态。
第二,在函数调用,传指针参数。无论你的对象或结构参数多么庞大,你用指针,传过去的就是4个字节。若是用对象,参数传递占用的资源就太大了
转自:http://blog.sina.com.cn/s/blog_73e0563201017c8u.html
此文章比较全面的总结了类对象和类指针使用的不一样
#include <iostream> #include <string> using namespace std; class Student { public: static int number; string name; public: Student() { } void set(string str) { name = str; number++; // 调用静态数据成员 } void print() // 态成员函数 print() { std::cout < < name < <" : The number of the students is " < < number < < " numbers." < < std::endl; // 调用静态数据成员 } }; int Student::number = 0; // 静态数据成员初始化 int main(int argc, char** argv) { Student* s1; s1 = new Student(); s1->set("111"); Student s2; s2.set("222"); s1->print(); s2.print(); return 0; }
对于类student ,定义了一个对象 和一个指针。
类的指针:他是一个内存地址值,他指向内存中存放的类对象(包括一些成员变量所赋的值).
对象,他是利用类的构造函数在内存中分配一块内存(包括一些成员变量所赋的值).
在应用时:
1.引用成员: 对象用" . "操做符; 指针用" -> "操做符.
2.生命期: 如果成员变量,则是类的析构函数来释放空间;如果函数中的临时变量,则做用域是该函数体内.而指针,则需利用delete 在相应的地方释放分配的内存块.
注意:用new ,必定要delete..
类的对象:用的是内存栈,是个局部的临时变量.
类的指针:用的是内存堆,是个永久变量,除非你释放它.
当类是有虚函数的基类,Func是它的一个虚函数,则调用Func时:
类的对象:调用的是它本身的Func;
类的指针:调用的是分配给它空间时那种类的Func;
对于一个类的对象和这个类的指针(用new运算符分配内存)在应用时有何区别
1.类和对象是两回事,对象是类的实例;
2.对象是在栈中分配的,使用new生成的对象是在堆中分配的;
3.要发挥虚函数的强大做用,必须使用指针来访问对象.
指针能够实现多态,直接用对象不行
执行定义对象,在栈空间
new的在堆
类型决定了你能作什么.
其实做用基本同样 都是为了调用类的成员变量 和成员函数用的
当你但愿明确使用这个类的时候,最好使用对象,若是你但愿使用C++中的动态绑定,则最好使用指针或者引用
指针和引用用起来更灵活,容易实现多态等
1.在类的声明还没有完成的状况下,能够声明指向该类的指针,可是不可声明该类的对象...
2.父类的指针能够指向子类的对象..
定义对象实例时,分配了内存。指针变量则未分配类对象所需内存,除非new了
指针变量是间接访问,但可实现多态(经过父类指针可调用子类对象),而且没有调用构造函数。
直接声明可直接访问,但不能实现多态,声明即调用了构造函数(已分配了内存)。
至于那个效率高要看程序调用过程而定。
C++的精髓之一就是多态性,只有指针或者引用能够达到多态。对象不行
用指针:
第一实现多态。
第二,在函数调用,传指针参数。无论你的对象或结构参数多么庞大,你用指针,传过去的就是4个字节。若是用对象,参数传递占用的资源就太大了
转自:http://www.cnblogs.com/ggjucheng/archive/2011/12/14/2287381.html
C++类就是为程序员提供一种创建一个新类型的工具,使这些新类型的使用可以像内部类型同样方便。
一个类就是一个用户定义的类型,如何声明一个类,形式以下:
class class_name { access_specifier_1: member1; access_specifier_2: member2; ... } object_names;
示例以下:
class Object { public: Object(); ~Object(); //must be public Object(int num); int getNumber(); void setNumber(int num); private: int m_num; };
如何定义一个已声明的类:
Object::Object() { m_num = 0; } Object::~Object() { } Object::Object(int num) { m_num = num; } int Object::getNumber() { return m_num; } void Object::setNumber(int num) { m_num = num; }
如何实例化和使用一个类:
int main () { Object obj1; Object obj2(110); Object obj3 = Object(119); Object *pObj4 = new Object(); Object *pObj5 = new Object(119); Object objs[10]; printf("obj1.getNumber() = %d\n", obj1.getNumber()); printf("obj2.getNumber() = %d\n", obj2.getNumber()); printf("obj3.getNumber() = %d\n", obj3.getNumber()); printf("pObj4->getNumber() = %d\n", pObj4->getNumber()); printf("pObj5->getNumber() = %d\n", pObj5->getNumber()); for (int i = 0; i < 10; i++) { printf("objs[%d].getNumber() = %d\n",i, objs[i].getNumber()); } delete pObj4; delete pObj5; return 0; }
类能够定义不只能够用关键字class,也能够用关键字struct和union。
class和struct的概念是类似的,可用struct和class声明C++的类(即struct能够有数据成员和函数成员)。二者之间惟一的区别是使用关键字struct声明的类成员默认状况下,是public访问权限,而使用关键字class声明的类成员默认是private访问权限。对于全部其余的目的,这两个关键字是等价的。
union的概念是与struct和class声明类不一样的,由于union一次只能存储一个数据成员,但union也可能拥有函数成员,union类的默认访问权限是public。
转自:http://blog.csdn.net/pearl333/article/details/8027358
对象与函数的关系(知道如何把对象指针和引用做为函数参数)
将对象指针做为函数的参数,传递给函数处理有两个好处
一、减小数据分配的时间和空间,提升了程序运行的效率;
二、在被调函数中,能够直接改变实参对象的值,实现函数之间的信息交换。
经过一个例子感觉 对象指针做为函数的参数
#include <iostream> using namespace std; class CPoint{ public : CPoint(int x,int y); void copy(CPoint *point); //在成员函数中,参数是对象指针 void setXY(int x,int y); void disp(); private: int m_x; //数据成员 int m_y; }; CPoint::CPoint(int x,int y) //带参数的构造函数 { m_x=x; m_y=y; } void CPoint::copy(CPoint *point) { m_x=point->m_x; //经过对象指针访问该对象的数据成员,赋值 m_y=point->m_y; //给调用成员函数的对象的数据成员 } void CPoint::disp(){ cout<<"x="<<m_x<<";y="<<m_y<<endl; } void CPoint::setXY(int x,int y){ m_x=x; m_y=y; } void func(CPoint *p){ //函数的参数是对象指针,经过指针调用对象的成员函数 p->setXY(55,33); } int main() { CPoint p1(5,5),p2(25,25); p1.copy(&p2); //把对象p2的地址赋值给对象指针 p1.disp(); func(&p2); //把对象p2的地址赋值给对象指针 p2.disp(); return 0; }
对象引用做为函数参数:比把对象指针做为函数参数更为广泛,由于使用对象引用做为函数参数不只具备对象指针的优势,并且使用对象引用更为直观和简单。因此在C++中广泛采用对象引用做为函数参数,看例子,注意对比上面的程序:
#include <iostream> using namespace std; class CPoint{ public : CPoint(int x,int y); void copy(CPoint &point); //在成员函数中,参数是对象指针 void setXY(int x,int y); void disp(); private: int m_x; //数据成员 int m_y; }; CPoint::CPoint(int x,int y) //带参数的构造函数 { m_x=x; m_y=y; } void CPoint::copy(CPoint &point) //函数的参数是对象引用 { m_x=point.m_x; //经过对象引用访问该对象数据成员,赋值给调用成员函数的对象的数据成员 m_y=point.m_y; } void CPoint::disp(){ cout<<"x="<<m_x<<";y="<<m_y<<endl; } void CPoint::setXY(int x,int y){ m_x=x; m_y=y; } void func(CPoint &p){ //在通常函数中,参数是对象引用,经过对象引用调用成员函数 p.setXY(55,33); } int main() { CPoint p1(5,5),p2(25,25); p1.copy(p2); //把对象p2的地址赋值给对象引用 p1.disp(); func(p2); //把对象p2的地址赋值给对象引用 p2.disp(); return 0; }
对象数组(一串连续的对象)
举一个例子来感觉对象数组的声明,初始化,和使用:
#include <iostream> #include<string.h> using namespace std; class CStudent{ public: CStudent(char *name,int age,int score);//构造函数 void disp(); private: char m_name[16]; //数据成员 int m_age; int m_score; }; CStudent::CStudent(char *name,int age,int score){ //构造函数的实现 strcpy(m_name,name); m_age=age; m_score=score; } void CStudent::disp() //显示构造函数 { cout<<"name:"<<m_name<<";age:"<<m_age<<";score:"<<m_score<<endl; } int main() { CStudent csArray[4]={CStudent("srf",24,96),CStudent("dp",23,95), CStudent("aa",24,98),CStudent("bb",24,99)}; for(int i=0;i<4;i++) { csArray[i].disp(); //对象数组中的对象调用其成员函数 } return 0; }
子对象和堆对象的声明和使用
一个类中的成员是另外一个类的对象时,称这个对象是子对象。换句话说,子对象就是类的对象成员。例以下面的橘子类(COrange)和苹果类(CApple):
class COrange { public: COrange(); private: ... }; class CApple { public: CApple(); private: COrange orange; //橘子类的子对象 };
CApple的成员orange是类COrange的对象,因此orange为子对象。当一个类中包含子对象时,这个类的构造函数中应该包含对该子对象的初始化后。而且只能采用成员初始化表的方法来初始化该子对象。经过例子感觉:
包含对象成员的类应用。
#include <iostream> #include<string.h> using namespace std; class COrange { public: COrange(int heft,int sweet); void disp(); private: int m_heft; int m_sweet; }; COrange::COrange(int heft,int sweet) { m_heft=heft; m_sweet=sweet; } void COrange::disp() { cout<<m_heft<<";"<<m_sweet<<endl; } class CApple { public: CApple(int heft,int sweet,int fragrant); void disp(); private: COrange orange; //声明COrange类的子对象orange int m_fragrant; //数据成员--香味 }; CApple::CApple(int heft,int sweet,int fragrant):orange(heft,sweet) { //用成员初始化列表的方式初始化子对象,格式为:子对象名(参数表) m_fragrant=fragrant; } void CApple::disp(){ orange.disp(); cout<<m_fragrant<<endl; } int main() { CApple apple(8,18,28); //定义CApple类的对象apple apple.disp(); return 0; }
堆对象:用类定义的对象有一种特殊的对象,能够在程序运行时,随时建立和删除,知足实时的程序要求,这种对象称为堆对象。
由于这种对象的内存空间是建立在堆内存中,因此能够像堆空间同样随时申请和释放,其操做符也是new和delete。
建立格式为:new 类名(参数名);
如:
CTest *p=NULL; //定义一个对象指针 p=new CTest(); //建立一个堆对象,并赋值给对象指针p
也能够建立堆对象数组
CTest *pa=NULL; pa = new CTest[5];
删除时:
delete p; //p是一个指向new建立的堆对象的对象指针 delete [] pa; //pa是一个指向new建立的堆对象数组的对象指针
经过一个例子来感觉对对象的建立,删除和使用。
#include <iostream> #include<string.h> using namespace std; class CHeap { public: CHeap(); CHeap(int a,int b); ~CHeap(); void disp(); private: int m_a,m_b; }; CHeap::CHeap() { m_a=0; m_b=0; cout<<"调用默认的构造函数"<<endl; } CHeap::CHeap(int a,int b) { m_a=a; m_b=b; cout<<"调用带参数的构造函数"<<endl; } CHeap::~CHeap() { cout<<"调用析构函数"<<endl; } void CHeap::disp() { cout<<"m_a="<<m_a<<";m_b="<<m_b<<endl; } int main() { CHeap *pheap; pheap=new CHeap(); //建立堆对象,并把地址赋值给pheap if(pheap) //判断是否建立成功 { pheap->disp(); //经过对象指针,调用堆对象的成员函数 delete pheap; //删除堆对象 } pheap = new CHeap(10,30); //把对象指针指向新的堆对象,使用参数构造。 if(pheap) { pheap->disp(); delete pheap; } return 0; }
堆对象若是建立失败,new返回是NULL值,即空指针,因此使用前必须进行判断,若是建立成功,则在最后不使用时,应当删除这个堆对象,并释放其占用的堆内存空间。
堆对象数组的建立,删除,和使用,只看主函数部分的修改:
int main() { CHeap *pheap; pheap=new CHeap[3]; //把对象指针指向堆对象数组的首元素 if(pheap) //判断是否建立成功 { for(int i=0;i<3;i++) { (pheap+i)->disp(); //调用对象数组中对象元素的成员函数 使用对象指针加增量来访问对象数组中的每一个对象元素 } delete []pheap; //删除堆对象数组 } return 0; }
转自:http://www.cnblogs.com/hellope/archive/2011/08/03/2126371.html
首先咱们先来了解一下MFC中的CPtrArray类,他能够说是CObject类型指针对象的集合。经过int Add(CObject* newElement );注意参数是一个指针类型)能够向集合中添加元素。首先咱们定义一个CPtrArray类型的对象。
CPtrArray pArray;//他是一个全局对象
先设定一个举例的类类型。如:
class A { public: A(int i) { a = i; } ~A(){} public: int a; };
如今咱们须要在某个函数中要实现将一个A类型对象数据加入到一个CPtrArray对象中。此函数func1()以下:
void func1() { //首先定义一个A类型的对象 A a(1); //使用pArray对象中的成员函数将此对象加入到容器中 pArray.Add(&a); }
在另外一个函数中咱们使用pArray容器为咱们保存的数据:
void func2() { //首先声明一个A类型的对象 A* a; //使用pArray对象中的成员函数GetAt()将A类型的对象取出 for(int i; i < pArray.GetSize();i++) { a = (A*)pArray.GetAt(i); //使用A中的数据进行相关的操做代码。***此时也可使用delete释放指针指向的内存区块,防止内存泄露***固然是后面一种方法时才用到,暂时无视之。 ... } }
如今咱们发现按照上面的过程,当咱们在func2()函数中将要使用pArray容器对象为咱们保存的数据时,咱们并不能获得想要的数据!!!为何发生以上状况?图解以下
pArray保存a保存资源的地址;
func1函数执行完成,a发生析构,资源不可用;
原来在func1()函数中,a对象是一个局部对象,当咱们使用pArray.Add(&a);咱们将a对象的地址保存到pArray对象中。可是做为局部对象,当func1
执行完成后,资源须要回收,此时咱们定义的a对象也在A类中的析构函数中被析构释放资源!而当咱们在fun2()函数中执行取出保存的对象时,
实际是根据保存的地址去内存中找到数据,虽然此时咱们能可以找到此地址,可是这个地址上面的数据并非咱们须要的了!!!因此才发生面的状况!
那么怎么才能解决呢?
看下面,咱们只需更改func1函数中的代码:
void func1() { //首先定义一个A类型的对象 //A a(1);//为对比,只是注释原来那句 A* a = new A(1); //使用pArray对象中的成员函数将此对象加入到容器中 pArray.Add(a); }
这样,咱们就可以在func2函数中使用pArray对象中包含的数据了!那么为何定义了一个指针类型的对象就可以完成了呢?仍是一个局部对象呀,
前面说的func1函数执行完成后此对象仍是要经历析构的啊!图解以下:
pArray中保存a指向资源的地址;
func1函数执行完成,a对象发生析构,pArray根据地址还能可以访问到以前的资源;
对,是要析构,可是,咱们在pArray.Add(a);中加入的是a对象资源的地址,咱们先看看A* a = new A(1);在堆中分配资源,咱们知道,在堆中分配的资
源是在跟程序的生命周期是一致的。a对象虽然析构了(不存在了),由于a也是一个指针,a指针也就是保存这个资源的地址!咱们在pArray中保存
的a的地址出的资源并无析构!因此在func2函数中咱们还可以使用此地址访问此地址对应的资源!