封装的实现
在类的定义的时候可以使用三种访问权限:
1、public (公有) 可以被该类中函数、子类函数、友元函数访问,也可以由该类的对象访问;
2、protected (保护)可以被该类中函数、子类函数、友元函数访问,不可以由该类的对象访问;
3、private (私有 默认)可以被该类中的函数、友元函数访问,不可以由子类函数、该类的对象、访问。
#pragma once
class student
{
public:
student(void);
void init(char *name,int age)
{
stu_name=name;
stu_age=age;
}
~student(void);
private:
char *stu_name;
int stu_age;
};
类的对象访问是: student x; x.stu_age=20;(错误,类的对象不能访问私有和保护成员变量)
成员函数访问是:init 函数里给成员变量赋值 (正确,自己的行为修改自己的状态)
友元函数、友元类是在类定义中主动指定某个函数或者类作为自己的友元(后面再介绍)。
静态和动态
普通的成员变量和成员函数默认是动态的,它们在编译的时候都会补上一个this指针,比如init函数在编译后:
void init(char *name,int age,student *this)
{
this->stu_name=name;
this->stu_age=age;
}
如果不带上this指针,不同对象调用init函数将相互影响,比如
student x,y; x.init("t1",10);
目标肯定是设置x对象的成员变量,但从语法意义上,init函数并没有指明要使用x对象的成员变量,所以动态带上对象的指针才能解决问题:
x.init("t1",10); 编译成 : x.init( "t1" ,10 , &x); 很显然与x对象进行了动态绑定,x,y的init就不会相互影响。
以上的实现很繁琐,C++则针对所有的动态成员和成员变量进行了隐藏,所以在每个动态(普通)成员函数中会有一个隐藏的this指针,它就指向调用该成员函数的对象本身。
除了动态成员变量函数,还有静态的。思考一下:纯面向对象思想的程序怎么运行? 程序运行是执行功能体,也就是需要函数调用。定义对象后才能调用功能体,而功能体里才能定义对象——产生一个悖论。
全局对象或者全局函数貌似可以,全局对象自动调用构造函数,全局函数直接加载功能函数即可,但是纯面向对象语言是没有全局对象和函数的。
静态成员函数和成员变量就可以派上用途了:与普通的成员函数不同:
1、静态成员函数和成员变量需要加上static 关键字;
2、静态成员函数和成员变量没有 this指针,静态成员函数当然不能使用普通的成员变量,静态成员函数只能使用静态成员变量;
3、静态成员函数和成员变量可以通过类调用(也称为类函数和类变量),当然也可以通过对象来调用:
#pragma once
class student
{
public:
student(void);
~student(void);
static void s_set(int data){
s_data=data;
//stu_age=10; 错误,不能调用普通成员变量
}
static int s_get()
{
return s_data;
}
private:
char *stu_name;
int stu_age;
static int s_data;
};
使用前在CPP文件中对静态变量进行初始化,初始化语句才真正完成了静态成员变量的定义:
#include "student.h"
//static int student::s_data=50; 错误,不能再加static
int student::s_data; //初始化静态成员变量(0) int student::s_data=20; 初始化为20
student::student(void)
{
}
student::~student(void)
{
}
#include <iostream>
#include "student.h"
using namespace std;
int main()
{
student::s_set(20); //类名调用静态成员函数
cout<<student::s_get()<<endl; //类名调用静态成员变量
student x;
x.s_set(50); //对象调用静态成员函数
cout<<x.s_get()<<endl; //对象调用静态成员变量
cout<<student::s_get()<<endl; //结果一样,表明静态成员变量只有一份(大家共用)
return 0;
}
4、静态成员函数在CPP文件中实现时也不能带static:
#include "student.h"
//static int student::s_data=50; 错误,不能再加static
int student::s_data=50; //初始化静态成员变量
student::student(void)
{
s_data=50; //必须有初始化语句才能调用
}
student::~student(void)
{
}
//static int student::s_get() 错误,不能再加static
int student::s_get() //静态成员函数的实现与普通函数一样
{
return s_data;
}
5、C++不是纯粹的面向对象语言,可以使用全局函数和全局变量,解决程序入口只需指定默认的主控函数即可;C++构造函数和析构函数不能定义成静态函数。
6、JAVA等高级语言也通过默认的规则使用静态函数完成程序入口:JAVA的主类(与应用程序同名的类)中必须有一个静态的main函数,执行JAVA程序,用文件名做类名去调用main函数。