二、C++特性

WIN32 Console Application

c++ source file

1、c++中类和结构体的区别

例如:

class Point
{
public:
 int x;
 int y;
 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)
 {
  this->x=x;
  this->y=y;
 }
};

结构体

struct  Point
{
 int x;
 int y;
 Point()
 {
  x=0;
  y=0;
 }
 ~Point()
 {
 }
 void output()
 {
  cout<<x<<endl<<y<<endl;
 }
};

在c++中,结构体成员可以是函数,而c中则不可以。默认情况下,struct的成员访问权限为public,而class为private。当成员为public时,在外部也可以访问;当为protect时,只能在子类中访问,不能在外部访问;当为private时,只能在当前类中访问。

 

 

2、构造函数

如1中的Point类中的Point()就是构造函数,系统自动调用构造函数初始化数据对象。

1)构造函数最重要的作用是创建对象本身 。
2)C++规定,每个类必须有一个构造函数,没有构造函数,就不能创建任何对象。
3)C++又规定,如果一个类没有提供任何的构造函数,则C++提供一个默认的构造函数(由C++编译器提供),这个默认的构造函数是一个不带参数的构造函数,它只负责创建对象,而不做任何的初始化工作。
4)只要一个类定义了一个构造函数,不管这个构造函数是否是带参数的构造函数,C++就不再提供默认的构造函数。也就是说,如果为一个类定义了一个带参数的构造函数,还想要无参数的构造函数,则必须自己定义。

 

3、析构函数

如1中的~Point()就是析构函数,释放内存。

1)当一个对象生命周期结束时,其所占有的内存空间就要被回收,这个工作就由析构函数来完成。
2)析构函数是“反向”的构造函数,析构函数不允许有返回值,更重要的是析构函数不允许带参数,并且一个类中只能有一个析构函数。
3)析构函数的作用正好与构造函数相反,对象超出其作用范围,对应的内存空间被系统收回或被程序用delete删除时,析构函数被调用。
4)根据析构函数的这种特点,我们可以在构造函数中初始化对象的某些成员变量,给其分配内存空间(堆内存),在析构函数中释放对象运行期间所申请的资源。

 

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 output(int x,int y)
 {
  this->x=x;
  this->y=y;
 }
};

void main()
{
 Point pt(3,3);
 pt.output(5,5);
// pt.init();
 //pt.x=5;
 //pt.y=5;
// cout<<pt.x<<endl<<pt.y<<endl;
 pt.output();
}

在这段程序中,类Point中的函数Point和output就属于函数重载。

在创建了Point的对象pt之后,就产生了一个隐含的this指针,指向pt对象。在void output(int x,int y)中,如果直接写x=x,这是output内部形参给自身赋值,也就是说第一个x并不是class point中定义的x,而是output的局部变量。这个属于参数的可见性问题。

5、函数的继承

首先看以下5个源文件

/1、Animal.h

#ifndef ANIMAL_H_H
#define ANIMAL_H_H
class Animal
{
public:
 Animal(int height,int weight);


 void eat();


 void sleep();
 
 virtual void breathe();//=0;
};

#endif

 

/2、Fish.h

#include "Animal.h"

#ifndef FISH_H_H
#define FISH_H_H
class Fish : public Animal
{
public:
 Fish();

 void breathe();
};
#endif

 

/3、Animal.cpp

#include "Animal.h"
#include <iostream.h>

Animal::Animal(int height,int weight)
{
}

void Animal::eat()
{
 cout<<"animal eat"<<endl;
}

void Animal::sleep()
{
 cout<<"animal sleep"<<endl;
}

void Animal::breathe()
{
 cout<<"aniaml breathe"<<endl;
}

/4、Fish.cpp

#include "Fish.h"
#include <iostream.h>
Fish::Fish():Animal(300,400)
{
}

void Fish::breathe()
{
 cout<<"fish bubble"<<endl;
}

/5、Main.cpp

#include <iostream.h>
#include "Animal.h"
#include "Fish.h"

void fn(Animal *pAn)
{
 pAn->breathe();
}


void main()
{
 //Animal an;
 //an.eat();

// an.breathe();
 Fish fh;
 Animal *pAn;
 pAn=&fh;
 fn(pAn);

}

由次可以看出编写一个类的一般顺序如下:

首先在头文件中声明一个类,并声明其成员变量,如数据变量,构造函数、析构函数、各种方法等;然后在其对应的cpp文件中实现各个成员函数的具体代码。(参见Animal)

 

子类的编写

首先在头文件中声明为子类,class Fish : public Animal,然后在其cpp文件中实现方法的代码。

**********函数的覆盖*********

在Animal.cpp中有构造函数如下:

Animal::Animal(int height,int weight)
{
}

而在Fish.cpp中

Fish::Fish():Animal(300,400)//注意此处传递参数的方法
{
}

这就是函数的覆盖。函数覆盖出现在父类与子类之间。覆盖使得当不需要父类的方法时,子类的方法可以替换父类的方法。

 

 

***********函数的多态性**********

***********虚函数************

在父类的头文件中:定义为virtual。当子类需要时,可以自己去编写相关代码。虚函数的使用原则如下:子类有的使用子类的,子类没有的使用父类的(前提是必须传递子类的地址,例如:

Fish fh;
 Animal *pAn;
 pAn=&fh;
 fn(pAn);

纯虚函数:virtual void breathe()=0;这时的虚函数是没有函数体的。在子类中必须实现它的函数体,例如:

void Fish::breathe()
{
 cout<<"fish bubble"<<endl;
}

注意:在虚函数定义时要用virtual,但在具体实现时不再使用virtual

 

给常量赋值的方法:

例如在Fish.h中,

private:

const int a;

 

在public中:

Fish():a(1);

 

 

引用

int a=6

int &b=a;

引用必须在声明的同时初始化。

引用与指针的区别:引用本身不占用地址空间,指针变量由于要存储地址,需要存储空间。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值