1. 类和对象
class Box
{
public://private 或 protected
double length; // 盒子的长度
double breadth; // 盒子的宽度
double height; // 盒子的高度
double getVolume(void) //类的成员函数
{
return length * breadth * height;
}
Box();//构造函数
Box(double length);//带参数的构造函数
~Box();//析构函数
Box(const Box &obj);// 拷贝构造函数
friend void printWidth( Box box ); //友元函数
private:
double *ptr;
};
Box::~Box(void)
{
cout << "Object is being deleted" << endl;
}
Box::Box(const Box &obj)
{
cout << "调用拷贝构造函数并为指针 ptr 分配内存" << endl;
ptr = new double;
*ptr = *obj.ptr; // 拷贝值
}
Box Box1;// 声明 Box1,类型为 Box
Box Box2;// 声明 Box2,类型为 Box
// box 1 详述
Box1.height = 5.0;
Box1.length = 6.0;
Box1.breadth = 7.0;
成员函数
除了可以在 class 内部定义成员函数,也可以在类的外部使用范围解析运算符 :: 定义该函数,如下:
double Box::getVolume(void)
{
return length * breadth * height;
}
:: 叫作用域区分符,指明一个函数属于哪个类或一个数据属于哪个类。
:: 可以不跟类名,表示全局数据或全局函数(即非成员函数)。
C++ 类访问修饰符
public、private、protected,成员和类的默认访问修饰符是 private。保护(protected)成员变量或函数与私有成员十分相似,但有一点不同,保护成员在派生类(即子类)中是可访问的,而 priavte 是不可以的。
类继承时使用修饰符
有public, protected, private三种继承方式,它们相应地改变了基类成员的访问属性。
- 1.public 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:public, protected
- 2.protected 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:protected, protected,有继承下来但说父类的成员不能被子类对象调用了
- 3.private 继承:基类 public 成员,protected 成员,private 成员的访问属性在派生类中分别变成:private, private,有继承下来但父类的成员不能被子类对象调用了
但无论哪种继承方式,上面两点都没有改变:
- 1.private 成员只能被本类成员(类内)和友元访问,不能被派生类访问;
- 2.protected 成员可以被派生类访问。
class B : public A{
}
类的构造函数
会在每次创建类的新对象时执行
注意一种带初始化列表的构造函数
C::C( double a, double b, double c): X(a), Y(b), Z(c)
{
....
}
//eg:
Box::Box( double len): length(len)
{
cout << "Object is being created, length = " << len << endl;
}
//相当于
Box::Box( double len)
{
cout << "Object is being created, length = " << len << endl;
length = len;
}
类的析构函数
在每次删除所创建的对象时执行
析构函数的名称与类的名称是完全相同的,只是在前面加了个波浪号(~)作为前缀,它不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源。
C++ 拷贝构造函数
拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。如果在类中没有定义拷贝构造函数,编译器会自行定义一个。拷贝构造函数通常用于:
- 通过使用另一个同类型的对象来初始化新创建的对象。
- 复制对象把它作为参数传递给函数。
- 复制对象,并从函数返回这个对象。
如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。拷贝构造函数的最常见形式如下:
classname (const classname &obj) {
// 构造函数的主体
}
C++ 友元函数
类的友元函数是定义在类外部,但有权访问类的所有私有(private)成员和保护(protected)成员。
尽管友元函数的原型有在类的定义中出现过,但是友元函数并不是成员函数。
友元可以是一个函数,该函数被称为友元函数;友元也可以是一个类,该类被称为友元类,在这种情况下,整个类及其所有成员都是友元。
#include
using namespace std;
class Box
{
double width;
public:
friend void printWidth( Box box );
void setWidth( double wid );
};
// 成员函数定义
void Box::setWidth( double wid )
{
width = wid;
}
// 请注意:printWidth() 不是任何类的成员函数
void printWidth( Box box )
{
/* 因为 printWidth() 是 Box 的友元,它可以直接访问该类的任何成员 */
cout << "Width of box : " << box.width <
C++ 内联函数inline
C++ 内联函数是通常与类一起使用。引入内联函数的目的是为了解决程序中函数调用的效率问题。如果一个函数是内联的,那么在编译时,编译器会把该函数的代码副本放置在每个调用该函数的地方。内联函数的定义只能是一行(编译器能正确的替换)。
C++ 类的静态成员
使用 static 关键字来把类成员定义为静态的,当声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本,在创建第一个对象时,所有的静态数据都会被初始化为零。
不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符:: 来重新声明静态变量从而对它进行初始化。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。
// 初始化类 Box 的静态成员
int Box::objectCount = 0;
静态成员函数与普通成员函数的区别:
- 静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)。
2. C++ 继承
class derived-class: access-specifier base-class, base-class
C++ 重载运算符和重载函数
C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载
//重载‘+’运算符,可以把 operator+ 当做函数名
Box operator+(const Box&);
Box operator+(const Box&, const Box&);
3. 多态
不同于 java,直接重写父类的同名函数,子类对象调用同名函数时被编译器设置为基类中的版本,这就是所谓的静态多态,或静态链接 - 函数调用在程序执行前就准备好了。有时候这也被称为早绑定,因为函数在程序编译期间就已经设置好了。
虚函数
虚函数 是在基类中使用关键字 virtual 声明的函数。在派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数。这种操作被称为动态链接,或后期绑定。
纯虚函数
可以在基类中声明一个虚函数,以便在派生类中重新定义该函数更好地适用于对象,基类中又不对虚函数给出有意义的实现,这个时候就会用到纯虚函数。
class Shape {
protected:
int width, height;
public:
Shape( int a=0, int b=0)
{
width = a;
height = b;
}
// pure virtual function
virtual int area() = 0;//= 0 告诉编译器,函数没有主体,上面的虚函数是纯虚函数。
};
C++ 接口(抽象类)
c++没有特定的关键字定义接口(抽象类)
C++ 接口是使用抽象类来实现的,如果类中至少有一个函数被声明为纯虚函数,则这个类就是抽象类。纯虚函数是通过在声明中使用 "= 0" 来指定的。抽象类不能被用于实例化对象,它只能作为接口使用。如果试图实例化一个抽象类的对象,会导致编译错误。