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;
引用必须在声明的同时初始化。
引用与指针的区别:引用本身不占用地址空间,指针变量由于要存储地址,需要存储空间。