C++小结1

来源:互联网 发布:淘宝主图尺寸高度 编辑:程序博客网 时间:2024/05/01 19:25
// Include file#include <iostream>using namespace std;//Struct define //struct Point// struct 和 class 在C++中功能几乎一样,只是访问功能上 class 更具有可控性// struct 没有对外被访问的功能 class 可以通过 public , protected , private来设置被//外界的访问权限, 如果class中没有显示指明为public, protected 则外部是不能访问class内部的成员和//和函数的, 而声明为protected  时 则继承类可以访问, 而外部类是不能访问// 结构体初始化成员默认是public的, 而class默认是private的//类是指抽象出事物的一个类, 而对象则指的是某一个类中的具体的实例class Point{public:int x;int y;// 构造函数, 最重要的作用, 是创建对象本身  构成函数负责分配对象的内存空间Point(){x = 0;y = 0;}Point(int a, int b){x = a;y = b;}// Point() 与Point(int a , int b) 这种函数名相同,但参数个数和类型不同,称之为函数重载~Point(){}//自己声明的一个初始化函数//void init()//{//x = 0;//y = 0;//}// c语言中结构体中是不能有函数的, 而C++中可以有, 所以C++中可以把函数封装到结构体中void output(){cout<<x<<endl<<y<<endl;}void output(int x , int y){//在这个函数体内, 之前在类开始的那个public下声明的int x, int y 在这个函数体内是不可见的//这是因为 void output(int x , int y) 中声明 的这两个形参x ,y和// public // int x ,// int y,// 这里声明的两个参数同名,导致在这个void output(int x , int y) 体内对public那个x, y是不可见的//也就是说这个函数中形参x, y 屏蔽了外部同名变量x,y在这个函数体内的可见性//所以在这里面操作的x = x , 和 y = y 是将自己的值赋值给自己,根本没有对外部的x,y复制, 所以导致外部调用void output()来输出时 还是// 构造函数初始化的值 3, 3// 这里的x = x 中的两个x实际是指的 void output(int x, int y) 中的x x = x;y = y;}//那么为了能够使之调用pt.output(5,5)最终输出的是 5, 5 有两种做法// 将void output (int a, int b)中的形参换成 a, b 这样因为不同名取消对外部变量x,y的屏蔽性/*void output(int a, int b){x = a;y = b;}*/// 第二种是利用对象的this 指针/*void output(int x ,int y){this->x = x;this->y = y;}*///this 指针是一个隐含的指针,它是指向对象本身,代表了对象的地址//这里, Point pt ; 即Point 声明了一个对象pt, 那么当pt调用output(int x,inty)函数时//这个this指针就代表的是pt的地址//一个类所有的对象调用的成员函数都是同一代码段。那么成员函数又是怎么识别属于同一对象的数据成员呢?//原来,在对象调用pt.output(10,10)时,成员函数除了接收了10,10这两个实参外, 还接收到了一个对象pt的地址//。这个地址被一个隐含的形参this指针所获取,它等同于执行this = &pt. //所有对数据成员的访问都隐含地被加上前缀this->。例如//x = 0; 等价于是this->x = 0;// 每当产生一个对象, 都有一个隐含的指针指向这个产生的对象// 对象是实例化的, 占据内存,而类是抽象的, 不占用内存}; // 注意加上分号 //void main()//{//Point pt(3,3);//// 结果是3,3不是5,5 why? //pt.output(5,5);// //pt.init();////pt.x = 6;////pt.y = 6;////cout<<pt.x<<endl<<pt.y<<endl;//pt.output();//getchar();//}

首先新建一个Win32 Console ApplicationEmpty Project项目,然后添加文件Point.cpp

因为要用到C++的标准输入输出流,所以要包含预处理文件

#include <iostream>

Using namespace std;

然后定义一个结构体 Point

struct Point

{

         //声明两个变量

      int x;

int y;

}; //注意结构体这个大括号后面要添加一个分号!

然后定一个main()函数

void main()

{

       声明一个结构体Point的实例变量

       Point pt;

       通过 . 运算符来获取结构体中的成员变量和函数 ,并输出

       cout<<pt.x<<endl<<pt.y<<endl;

}

点击运行, 此时将输出两个比较大的随机值, 这是因为, Point中声明的两个变量x,y,并没有被初始化,所以它们所指内存中的值是随机的,首先我们可以通过下面的方式来为x,y指定相应的值

void main()

{

       Point pt;

       pt.x = 6;

       pt.y = 6;

       cout<<pt.x<<endl<<pt.y<<endl;

       getchar();

}

也可以在结构体中增加一个output()来负责输出的功能

struct Point

{

         int x;

         int y;

         void output()

{

         cout<<x<<endl<<y<<endl;

}

};

此时注释掉main中的cout,并通过pt调用output来输出,结果是一样的

void main()

{

Point pt;

       pt.x = 6;

       pt.y = 6;

       //cout<<pt.x<<endl<<pt.y<<endl;

       pt.output();

       getchar();

}

这里要注意的是, C语言中结构体中是不能够有函数的,而在C++结构体中则可以有,所以可以将一些功能封装到结构体内部的成员函数当中。

由此可以在结构体中声明一个init()方法来初始化x,y

struct Point

{

         int x;

         int y;

         void init()

{

         x = 0;

         y = 0;

}

void output()

         {

                   cout<<x<<endl<<y<<endl;

}

};

void main()

{

         Point pt;

         pt.output();

         getchar();

}

这样会输出0,0

下面把结构体换成类

class Point

{

public:

         int x;

         int y;

         void output()

         {

                   cout<<x<<endl<<y<<endl;

}

};

即用这个类来代替上面的结构体, 运行结果是一样的

C++中,结构体和类可以通用,结构体也是一种特殊的类,struct class C++中功能几乎一样,只是访问的权限不同,class更具有可控性,struct没有控制外部访问权限的功能, class可以通过public,protected,private来设置外界的访问权限。如果class中没有明显的指明为public, protected 则默认是private类型,则外部是不能访问class内部的成员和函数的,而声明为protected时,则继承类可以访问,而外部类则不能访问。

类是指抽象出事物的一个类,而对象则指的是某一个类中的具体实例

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();

         getchar();

}

如果我们忘记了通过pt.x = 5 ; pt.y = 5 x,y 赋值 那么就会输出一个随机的值,显然这不是我们想要的

那怎么办? 可以在class类中自己声明一个初始化函数

void init()

{

         x = 0;

         y = 0;

}

然后在main()

pt.init(); 即可, 但是有时候可能也忘记了用pt 来调用init()这个函数,那怎么办呢?

那我们希望在Point pt; 在产生pt这个对象时, x,y就赋值了一个初值呢?那这里可以通过使用构造函数来实现,

Point()

{

         x=0;

         y=0;

}// 注意构造函数是没有返回值的哈,同时为了保证它的唯一性,所以它的名字采用了与类名相同

那当用Point 来实例化一个对象pt就会去调用 Point()这个构造函数来初始化x,y的值。

构造函数初始化成员变量,创建对象本身,并负责分配对象的内存空间。并且C++规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。如果一个类没有提供任何的构造函数, C++提供了一个默认的构造函数(由C++编译器提供),这个默认的构造函数是一个不带参数的构造函数,它只负责创建对象,而不做任务的初始化工作。只要一个类定义了一个构造函数,不管这个构造函数是否是带参数 的构造函数,C++就不再提供默认的构造函数。也就是说,如果为一个类定义了一个带参数的构造函数,要想要无参数的构造函数,则需要自己显示定义。

构造函数负责创建对象,并为对像分配内存空间, 那么用完之后怎么收回呢? C++定义了一个析构函数来负责回收无用的内存空间。析构函数是“反向”的构造函数,不充许有返回值,更重要的是析构函数不充许带参数,并且一个类中只能有一个析构函数。

~Point()

{}

那么构造函数可以有带参数的, 当同时声明了带参数和不带参的构造函数时

Point()

{}

Point(int height , int weight)

{}

那么Point()Point(int height, int weight)这中在同一个类中函数名相同,但参数的个数和类型不同,称之为函数重载(overload

在定义一个带参的构造函数

Point(int a, int b)

{

         x=a;

         y=b;

}

那么在定义的时候可以 Point pt(3,3);

那么pt.output();时会输出33

下面定一个output(int x, int y)重载的函数

void output(int x, int y)

{

x = x;

y = y;

}

那么在main

Point pt(3,3);

pt.output(5,5); 然后pt.output();但是输出的是33  那这是Why?

这是变量可见性的问题, 在这个函数体内,之前在类开始处那个public下声明的int x, int y在这个函数体内是不可见的, 这是因为, void output(int x, int y)中声明的这两个形参x, y

public

int x ;

int y;

这里声明的两个变量的名字相同, 所以导致在这个void output(int x, int y) 体内对public那两个 x , y 是不可见的,也就是说这个函数中形参x, y屏蔽了外部同名变量x,y在这个函数体内的可见性,所以在这个函数体内对x,y的所有操作其实都是对形参x,y进行的操作,即在这里面操作的 x= x ; y = y; 是将x,y自己的值赋值给自己,根本没有对外部的x,y赋值,所以导致外部调用 void output输出时,还是输出构造函数初始化的3,3. 这里的x=x 中的两个x 实际都是指 void output(int x, inty)中的形参x

那么为了能够使之调用pt.output(5,5)最终输出5有两种做法

第一种

void output(int x, int y )中的形参名称换成不是跟public下那个两个变量x,y同名,例如void output(int a, int b) 这样因为不同名就解除了对外部同名变量的可见性

void output(int a , int b)

{

         x = a;

         y = b;

}

第二种方法是利用对象的this 指针

void output(int x, int y)

{

         this->x = x;

         this->y = y;

}

这里的this指针是一个隐含的指针,它是指向对象本身的,代表了对象的地址,main()中 Point pt; Point 实例化了一个对象pt;那么当pt 调用output(int x, int y )时, 这个this指针就代表的是pt 这个对象的地址,那么 this -> x  操作的这个x Point实例化 pt调用构造函数初始化的那个x output(int x, inty)中的形参x不是同一个x

一个类所有的对象调用的成员函数都是同一代码段。那么成员函数又是如何识别属于同一对象的数据成员呢?原来,在对象调用pt.output(10,10)时,成员函数除了接收到了1010这两个实参之外,还接收到了一个对象pt的地址。这个地址被一个隐含的形参this指针所获取,它等同于执行this =&pt.所有对数据成员的访问都隐含地被加上前缀this->例如 x = 0; 等价于 this->x = 0;

每当产生一个对象, 都有一个隐含的指针指向这个产生的对象,对象是实例化的,占据内存,而类是抽象的,不占据内存。

 

 

原创粉丝点击