不管怎么讲,C++ 的一个代码还是运行出来了,准确点是vc++ ,虽然我现在并不清楚他们的区别。还是把我的着第一个程序代码贴出来。亦为记。
struct Point
{
int x;
int y;
};
void main()
{
Point pt;
pt.x=5;
pt.y=5;
cout<<pt.x<<endl<<pt.y<<endl;
}
也可以修改为:
struct Point
{
int x;
int y;
void outPut()
{
cout<<x<<endl<<y<<endl;
}
};
void main()
{
Point pt;
pt.x=56;
pt.y=5;
pt.outPut();
//cout<<pt.x<<endl<<pt.y<<endl;
}
这里,函数被包含进了结构图当中,而在c语言中,结构体中是不能包含函数的。这样,我们就可以讲一些操作封装进结构图的内部,使用的时候只需要调用结构体内的方法就可以。
class Point
{
public:
int x;
int y;
void outPut()
{
cout<<x<<endl<<y<<endl;
}
};
void main()
{
Point pt;
pt.x=5;
pt.y=5;
pt.outPut();
//cout<<pt.x<<endl<<pt.y<<endl;
}
这里的改动很小,把关键词struct 改为了class,加上了class 标识符,这跟前面的运行结构都是一样的。在c++中,结构体和类可以通用,结构体也是一种特殊的类,这里的struct和类还是有一定的区别,他们的区别主要在访问控制方面,比如,在上面的程序中,将public 注释,编译,报错“不能访问类中的私有成员”,在结构体中,所有的成员缺省情况都是public ,也就是在外部都是可以直接访问的。而对于一个类来讲,所有的函数和成员在默认的情况下都是私有的,不能够被外部访问。
数据成员和成员函数,
类的一个实例就是一个对象
把所有的方法放在类上,替代使用参数,方法的方式,使得方法由实例或者是方法来提供
下面假设我们忘记给x和y赋值,来检查运行的结果
#include <iostream.h>
class Point
{
public:
int x;
int y;
void outPut()
{ cout<<x<<endl<<y<<endl;
}
};
void main()
{
Point pt;
//pt.x=5;
//pt.y=5;
pt.outPut();
//cout<<pt.x<<endl<<pt.y<<endl;
}
运行结果:
-858993460
-858993460
可以看到,这是两个很大的负数,这是因为在没有赋值的情况下,系统随机给x、y赋予了这些值,(我觉得好像也不是任意随机的拉)
针对这样的情况,我们可以采用如下的方法,直接在类中加上初始化的函数,然后实例化类后再调用这个初始的函数就可以了。如下:
#include <iostream.h>
class Point
{
public:
int x;
int y;
void init()
{
x=0;
y=0;
}
void outPut()
{
cout<<x<<endl<<y<<endl;
}
};
void main()
{
Point pt;
pt.init();
//pt.x=5;
//pt.y=5;
pt.outPut();
//cout<<pt.x<<endl<<pt.y<<endl;
}
运行结果如下:
0
0
然而有的时候呢,我们会忘记去调用这个初始化的函数,而实际上呢,c++已经帮我们想好了,好,现在该构造函数出场了。
class Point
{
public:
int x;
int y;
/* void init()
{
x=0;
y=0;
}
*/
Point()
{
x=0;
y=0;
}
void outPut()
{
cout<<x<<endl<<y<<endl;
}
};
void main()
{
Point pt;
// pt.init();
//pt.x=5;
//pt.y=5;
pt.outPut();
//cout<<pt.x<<endl<<pt.y<<endl;
}
上面程序中,pt.init();已经被注释了,在类中,我加上了这么一个特殊的函数,函数的名字就是类的名字,大小写要一致,并且这个函数没有返回值。
上面的函数的运行结果呢,也是
0
0
虽然我们没有去调用这个构造函数,但是x,y 是已经被初始化的了。关于函数执行顺序,可以通过设置断点,F5 或者是F10(单步执行step over)进行查看。
构造函数作用
1.初始化内部的数据成员,更重要的作用是创建对象本身
2.C++规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。
3.C++规定,如果一个类没有提供任何的构造函数,C++会提供一个默认的构造函数(由编译器提供),这个默认的构造函数是一个不带任何参数的构造函数,它只负责创建对象,而不做任何的初始化工作。(这就是在我们前面程序中,没有使用任何构造函数,但也创建了实例的原因)
4.只要一个类定义了一个构造函数,不管是否是带参数的构造函数,C++ 就不再提供默认的构造函数。也就是说,如果为一个类定义了一个带参数的构造函数,还想要无参的构造函数,则必须自己定义。
既然创建了一个对象,就会在计算机中占据一定的内存,而内存的分配,就是由构造函数来完成。
好,上面在对象的生成的时候,为对象分配了一定内存空间,同样,在对象使用结束的时候,c++ 也提供了对象的销毁函数,这样呢,在程序完成后(生命周期结束),会调用析构函数,释放内存。
例子如下:
#include <iostream.h>
class Point
{
public:
int x;
int y;
/* void init()
{
x=0;
y=0;
}
*/
Point()
{
x=0;
y=0;
}
~Point()
{
}
void outPut()
{
cout<<x<<endl<<y<<endl;
}
};
void main()
{
Point pt;
// pt.init();
//pt.x=5;
//pt.y=5;
pt.outPut();
//cout<<pt.x<<endl<<pt.y<<endl;
}
构造函数和析构函数都是系统自动完成的。
析构函数特性:
1.当一个对象的生命周期结束时,其所占用的内存空间就要被回收,这个工作由析构函数完成。
2.析构函数是反向的构造函数,析构函数不允许有返回值,更重要的是析构函数不能带任何参数,并且一个类中只能有一个析构函数。
3.析构函数的作用和构造函数作用相反,对象超出其作用范围,对应的内存空间被系统回收或者程序用delete删除时,析构函数会被调用。
4.根据析构函数的这种特点,我们可以在构造函数中初始化对象的某些成员变量,给其分配内存空间(堆内存),在析构函数中释放对象在运行期间申请的资源空间。
现在我们看看什么有参的构造函数
#include <iostream.h>
class Point
{
public:
int x;
int y;
/* void init()
{
x=0;
y=0;
}
*/
Point()
{
x=0;
y=0;
}
Point(int a,int b)
{
x=a;
y=b;
}
~Point()
{
}
void outPut()
{
cout<<x<<endl<<y<<endl;
}
};
void main()
{
Point pt(3,3);
// pt.init();
//pt.x=5;
//pt.y=5;
pt.outPut();
//cout<<pt.x<<endl<<pt.y<<endl;
}
有参的构造函数和无参的构造函数的名称是一样的,曰:函数的重载。
函数重载构成的条件:函数的参数类型,参数的个数不同,才能构成函数的重载。
Viod outPut() 和int outPut() 是不能构成重载函数的。//只有返回值不同的函数不能构成重载
Void output(int a, int b=5) 和void output(int a )也是不能构成函数重载的,第一个是函数的第二个参数是个缺省值,实际上,这个参数的调用只要一个参数即可。
class Point
{
public:
int x;
int y;
/* void init()
{
x=0;
y=0;
}
*/
Point()
{
x=0;
y=0;
}
Point(int a,int b)
{
x=a;
y=b;
}
~Point()
{
}
void outPut()
{
cout<<x<<endl<<y<<endl;
}
void outPut(int x,int y)
{
x=x;
y=y;
}
};
void main()
{
Point pt(3,3);
pt.outPut(5,5);
// pt.init();
//pt.x=5;
//pt.y=5;
pt.outPut();
//cout<<pt.x<<endl<<pt.y<<endl;
}
上面并没有完成我们想要的功能,这实际上是变量的一个可见性的问题,
void outPut(int x,int y)
{
x=x;
y=y;
}
结果:
3
3
我们所有的操作,实际上都是对形参进行的操作,而整个个外面的x.,y 成员变量是没有受到任何的影响。
我们也可以将output(int x, int y)换为a,b,这样是可以的。
#include <iostream.h>
class Point
{
public:
int x;
int y;
/* void init()
{
x=0;
y=0;
}
*/
Point()
{
x=0;
y=0;
}
Point(int a,int b)
{
x=a;
y=b;
}
~Point()
{
}
void outPut()
{
cout<<x<<endl<<y<<endl;
}
void outPut(int a,int b)
{
x=a;
y=b;
}
};
void main()
{
Point pt(3,3);
pt.outPut(5,5);
// pt.init();
//pt.x=5;
//pt.y=5;
pt.outPut();
//cout<<pt.x<<endl<<pt.y<<endl;
}
结果
5
5
假设我们还是想用x,y 来表示形参,可以改为下面的形式
void outPut(int x,int y)
{
this->x=x;
this->y=y;
}
这样,运行结果
5
5
其中的 this 指的是对象本身。
关于this指针
1.this指针是一个隐含指针,它指向对象(而不是类)的本身,代表了对象的地址。
2.一个类所有的对象调用的成员函数都是同一代码段。
在对象调用pt.outPut(10,10)时候,成员函数除了接收两个实参之外,还接收了一个对象的地址 ,这个地址被一个隐含的形参指针this所获取,等同于执行 this=&pt。所有对数据成员的访问都被隐含加上了前缀this->.如x=0,等价与this->x=0.
贴出来回看了一下,咋个是这么的不友好,以后再接再厉。