类
class Box
{
public:
double length; // 盒子的长度
double breadth; // 盒子的宽度
double height; // 盒子的高度
};
类成员的作用域:
public:公共成员。访问权限:外部、子类、本身
protected:受保护成员。访问权限:子类、本身
private:私有成员。访问权限:本身
构造函数
跟其他语言一样,使用类名作为函数名,无返回值,可以有参数。
#include <iostream>
using namespace std;
class Line
{
public:
void setLength( double len );
double getLength( void );
Line(); // 这是构造函数
private:
double length;
};
// 成员函数定义,包括构造函数
Line::Line(void)
{
cout << "Object is being created" << endl;
}
void Line::setLength( double len )
{
length = len;
}
double Line::getLength( void )
{
return length;
}
// 程序的主函数
int main( )
{
Line line;
// 设置长度
line.setLength(6.0);
cout << "Length of line : " << line.getLength() <<endl;
return 0;
}
如果是带参数的构造函数,可以使用初始化列表:
Line::Line( double len): length(len)
{
cout << "Object is being created, length = " << len << endl;
}
上面的语法等同于如下语法:
Line::Line( double len)
{
cout << "Object is being created, length = " << len << endl;
length = len;
}
如果有多个参数,中间用逗号隔开:
Line::Line( double len): length(len), para02(var02)
{
cout << "Object is being created, length = " << len << endl;
}
另外,初始化列表并不是构造函数专用的,类的普通成员函数也可以使用。
析构函数
这个挺新鲜的,作用跟构造函数正好相反,在对象被销毁的时候执行。
无返回值,无参数,所以无法重载,一个类只能有一个析构函数
函数名也是与类同名,只需要在前面加一个波浪线前桌:~
在析构函数中,主要用来销毁在构造函数或成员方法里 new 出来的对象或指针,最常用的就是:delete obj
#include <stdio.h>
#include <iostream>
#include <vector>
using namespace std;
struct CP
{
int a;
int b;
};
class TEST
{
public:
CP* compound;
int num;
TEST(){
compound = new CP();
cout << "create a new TEST obj" << endl;
};
~TEST(){
cout << "delete TEST obj" << endl;
delete compound;
};
};
类的继承
跟JAVA不同,C++中允许一个类继承多个父类:
#include <iostream>
using namespace std;
// 基类 Shape
class Shape
{
public:
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
// 基类 PaintCost
class PaintCost
{
public:
int getCost(int area)
{
return area * 70;
}
};
// 派生类
class Rectangle: public Shape, public PaintCost
{
public:
int getArea()
{
return (width * height);
}
};
int main(void)
{
Rectangle Rect;
int area;
Rect.setWidth(5);
Rect.setHeight(7);
area = Rect.getArea();
// 输出对象的面积
cout << "Total area: " << Rect.getArea() << endl;
// 输出总花费
cout << "Total paint cost: $" << Rect.getCost(area) << endl;
return 0;
}
输出:
Total area: 35
Total paint cost: $2450
虚函数
这个不太好理解,只能按照别人的描述硬性记忆:在类的成员函数前面加 virtual 表示该成员函数为虚函数。
虚函数在C++中的作用不低,很多官方的源码中都存在大量的虚函数
目前位置能理解的作用包括:
1、允许用基类的指针来调用子类的这个函数:
class A
{
public:
virtual void foo()
{
cout<<"A::foo() is called"<<endl;
}
};
class B : public A
{
public:
void foo()
{
cout<<"B::foo() is called"<<endl;
}
};
int main(void)
{
A *a = new B();
a->foo(); // 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的!
return 0;
}
2、通过“纯虚函数”实现抽象类
虚函数:
virtual ReturnType funtion1(params...);
虚函数在基类中可以有默认实现,派生类也可以覆盖;
但如果在基类中没有默认实现,那么派生类必须具体实现。
纯虚函数:
virtual ReturnType funtion1(params...)=0;
在虚函数声明的后面加“=0”就表示这是一个纯虚函数,含有纯虚函数的类成为抽象类。
纯虚函数用来规范派生类的行为,即接口。派生类中必须对这个纯虚函数进行具体实现。
抽象类不能定义实例,但可以声明指向实现该抽象类的具体类的指针或引用。
对虚函数的理解,有一个很好的比方:
比如你有个游戏,里面有个含有纯虚函数 [攻击] 的抽象类 [怪物],然后有三个派生子类 [狼]、[蜘蛛]、[蛇] 都继承了 [怪物],并且都各自实现了自己独特的 [攻击] 函数。
那在出现怪物的时候就可以定义一个 虚基类指针数组,把各种怪物的指针给它,然后迭代循环的时候直接:怪物[i]->攻击() 攻击玩家就行了
Monster *pMonster[3];
pMonster[0] = new Wolf(); //初始化一匹狼
pMonster[1] = new Spider(); //初始化一只蜘蛛
pMonster[2] = new Snake(); //初始化一条蛇
for(int i=0; i<3; i++){
pMonster[i] -> attack(); //攻击
}
双冒号(::)
1、调用 namespace 中的成员时,需要用 ::
2、在类的外部定义成员函数时,需要用::
3、区别两个类中同名的成员变量或者函数时,需要用::
4、在成员函数内部调用同名的全局变量时,需要用::
5、调用类的静态成员函数时,可以用::