定义成员函数
所有成员都必须在类内声明,但是成员函数可以定义在类内也可以定义在类外。
std::string isbn() const { return bookno;}
??? isbn函数是如何获得bookno成员所依赖的对象呢?紧随参数列表之后的const关键字是怎么回事???
引入this
成员函数通过一个名为this的额外的隐式参数来访问调用它的那个对象,当我们调用成员函数时,实际上是在替某个对象调用它,用请求该函数的对象地址初始化this。
比如:
Sales_data total;
total.isbn(); //当isbn返回bookno时,隐式的返回total.bookno
等价于伪代码 Sales_data::isbn(&total)
,其中调用isbn成员时传入了total的地址。
this的目的总是指向“这个对象”,所以this是一个常量指针,不允许改变this中保存的地址。
引入const成员函数
isbn函数中 紧随参数列表之后的const关键字,作用是修改隐式this指针的类型。
默认情况下,this的类型是指向类类型非常量的常量指针,这意味着默认情况下我们不能把this绑定到一个常量对象上。这一情况使得我们不能在一个常量对象上调用普通的成员函数,但实际上isbn函数体内不会改变this所指的对象,所以把this设置为指向常量的指针有助于提高函数的灵活性。
面向对象程序设计中,为了体现封装性,通常不允许直接修改类对象的数据成员。若要修改类对象,应调用公有成员函数来完成。为了保证const对象的常量性,编译器须区分不安全与安全的成员函数(即区分试图修改类对象与不修改类对象的函数)。
在C++中,只有被声明为const的成员函数才能被一个const类对象调用。要声明一个const类型的类成员函数,只需要在成员函数参数列表后加上关键字const,这样的成员函数被称为常量成员函数。
总结:
1)const成员函数可以访问非const对象的非const数据成员、const数据成员,也可以访问const对象内的所有数据成员;
2)非const成员函数可以访问非const对象的非const数据成员、const数据成员,但不可以访问const对象的任意数据成员;
3)作为一种良好的编程风格,在声明一个成员函数时,若该成员函数并不对数据成员进行修改操作,应尽可能将该成员函数声明为const 成员函数。
4 ) 常量对象,以及常量对象的引用或指针都只能调用常量成员函数。
类作用域
类本身就是一个作用域,编译器分两步处理类,首先编译成员的声明,然后才轮到成员函数体(如果有的话)。因此,成员函数可随意使用类中的其他成员而无须在意这些成员出现的次序。
定义一个返回this对象的函数
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
units_sold += rhs.units_sold;
revenue += rhs.revenue;
return *this; //返回调用函数的对象
}
当我们调用如下的函数时,total.combine(trans);
total 的地址被绑定到隐式的this参数上,而rhs绑定到了trans上。因此当执行units_sold += rhs.units_sold 时,效果等同于求total.units_sold和trans.units_sold的和,然后把结果保存到total.units_sold中。
static静态成员变量
如果想在同类的多个对象之间实现数据共享,也不要用全局变量,那么可以使用静态成员变量。
/*************************************************************************
> File Name: static.cpp
> Author: Tanswer_
> Mail: 98duxm@gmail.com
> Created Time: 2016年09月28日 星期三 23时23分08秒
************************************************************************/
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <set>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <stack>
#include <queue>
using namespace std;
class Student
{
private:
string name;
int age;
float score;
static int num;
static float total;
public:
void Display();
Student(string, int ,float);
static float GetAve(); //静态成员函数
};
int Student::num = 0; //初始化静态成员变量
float Student::total = 0;
Student::Student(string name1,int age1,float score1)
{
this -> name = name1;
this -> age = age1;
this -> score = score1;
num++;
total += score1;
}
void Student::Display()
{
cout << name << "的年龄" << age << ",分数为 " << score ;
cout << "当前公有" << num << "名学生" << endl;
}
float Student::GetAve()
{
return total / num;
}
int main()
{
//使用匿名对象
(new Student("小明",19,80)) -> Display();
(new Student("小红",20,85)) -> Display();
(new Student("小华",21,90)) -> Display();
(new Student("小画",22,95)) -> Display();
cout << "平均成绩为: " << Student::GetAve() << endl;
return 0;
}
- static 成员变量属于类,不属于某个具体的对象,这就意味着,即使创建多个对象,也只为 num 分配一份内存,所有对象使用的都是这份内存中的数据。当某个对象修改了 num,也会影响到其他对象,所有对象共享这些静态变量。
- static 成员变量必须先初始化才能使用,而且只能在类体外进行,否则链接错误。
- static 成员变量的内存空间既不是在声明类时分配,也不是在创建对象时分配,而是在初始化时分配。
- static 成员变量与对象无关,不占用对象的内存,而是在所有对象之外开辟内存,即使不创建对象也可以访问,访问的是同一块内存。
- 访问成员变量的方式:
//通过类来访问
Student::num = 10;
//通过对象来访问
Student stu;
stu.num = 10;
static静态成员函数
当调用一个对象的成员函数(非静态成员函数)时,系统会把当前对象的起始地址赋给 this 指针。而静态成员函数并不属于某一对象,它与任何对象都无关,因此静态成员函数没有 this 指针。既然它没有指向某一对象,就无法对该对象中的非静态成员进行访问。
静态成员函数可以直接引用本类中的静态数据成员,因为静态成员同样是属于类的,可以直接引用。在C++程序中,静态成员函数主要用来访问静态数据成员,而不访问非静态成员。
上面实例代码中,定义了total 和 num 两个静态成员变量,定义了GetAve() 静态成员函数,只使用了total 和 num 两个静态成员变量。