类声明
公有、私有、保护成员
数据抽象和封装
注:ide是一个集成开发环境
头文件的编写
#ifndef _CLOCK_H_
#define _CLOCK_H_
#endif
目的是为了防止头文件被重复使用
编写规范:在数据成员后面加下划线
int hour_;
int minute_;
成员函数
Init();Display();
在关键字public后面声明,它们是类与外部的接口,任何外部函数都可以访问公有类型数据和函数。
在关键字private后面声明,只允许本类中的函数访问,而类外部的任何函数都不能访问。
在关键字protected后面声明,与private类似,其差别表现在继承与派生时对派生类的影响不同
注:保护成员,类外不能访问它,这是它与public的最大差别
数据抽象是一种依赖于接口和实现分离的编程(和设计)技术。类设计者必须关心类是如何实现的,但使用该类的程序员不必了解这些细节。使用者只要抽象地考虑该类型做什么,而不必具体地考虑该类如何工作。
注:只需要关心功能,只要这个类所提供的功能不变,也就是类所暴露的接口不变稳定,那对类使用者所编写的代码就是稳定的
class Stack
{
public:
void Push(int elem);
int Pop();
private:
};
封装是一项将低层次的元素组合起来形成新的、高层次的实体的技术。函数是封装的一种形式:函数所执行的细节行为被封装在函数这个更大的实体中。被封装的元素隐藏了它们的实现细节——可以调用函数,但是不能直接访问函数所执行的语句。同样地,类也是一个封装的实体:它代表若干成员的聚集,设计良好的类隐藏了类实现的细节。
并非给客户越多的东西就是越好的服务,相反,仅仅给他需要关注的东西才是最好的服务
这样子能防止粗心的程序员破坏内部的数据结构
内联函数:体积增大,以空间换时间
内联函数的实现:
一 在实现的时候给出
inline int Test::Add(int a,int b)
{
return a+b;
}
二 在定义的时候给出
int Add(int a,int b)
{
return a+b;
}
成员函数的重载及其缺省参数
必须在相同的作用域
void Init();
void Init(int x);
void Init(int x,int y);
void Init(int x,int y,int z);
也可以使用缺省参数
void Init(int x = 0;int y = 0;int z = 0);
在实现的时候不需要给定,vc助手会帮助我们实现这个功能
void Test::Init(int x,int y,int z)
{
}
class与struct的区别:
在未指定访问权限时,class默认的是私有的,struct默认是公有的
struct也可以有成员函数(但是只能在c++中才可以)
要详细说明this指针,必须深入了解类的内存模型
成员函数有一个隐含的附加形参,即指向该对象的指针,这个隐含的形参叫做this指针,
(由编译器来完成,主要是辨别每个对象,指向我们所构造的对象,从而让成员函数的代码有用)
使用this指针保证了每个对象可以拥有不同的数据成员,但处理这些成员的代码可以被所有对象共享
成员函数是共享的,如何知道初始化的是t1对象还是t2对象呢?这时候this指针就派上用场了!this指向对象本身
t1.Init(&t1,10,20,30) 所以传递了四个参数,编译器帮我们自动传递了此变量
类作用域:
#include<iostream>
using namespace std;
class Test
{
public:
int num_;
};
//num = 10;
int num_ = 20;//num_的作用域是文件作用域,与类中的num_是不同的作用域
//a 与b称为函数原型作用域 变量是可以省去的
int add(int a,int b);
int main(void)
{
int num_ = 30;//num_为块作用域
{
int num_ = 100;//num_为块作用域
}
cout<<num_<<endl;
cout<<::num_<<endl;
return 0;
}
int add(int a,int b) //形参a与b也称为块作用域
{
return a+b;
}
int test()
{
LABEL1: //label是一个标识符
cout<<"label"<<endl;
goto LABEL2;
LABEL2:
cout<<"label2"<<endl;
goto LABEL1;
}
两个类需要相互引用形成一个“环形”引用时,无法先定义使用。这时候需要用到前向声明
前向声明的类不能实例化!
A.H:
#ifndef _A_H_
#define _A_H_
#include "B.h"
class A
{
public:
A(void);
~A(void);
B b_;
};
#endif
B.H:
#ifndef _B_H_
#define _B_H_
#include "A.h"
class B
{
public:
B(void);
~B(void);
A a_;
};
#endif
A.H与B.H相互包含是不可以的!!因为环形包含!
所以必须在一个文件中做出相应的改变 不改变A.h 我们改变B.h
#ifndef _B_H_
#define _B_H_
//所以要用到前向声明
//而且只能用指针或者是引用
class A;
class B
{
public:
B(void);
~B(void);
// Error A a_;
A* a_; //前向声明的类不能实例化对象,无法分配内存,但可以定义
//指针或者引用
void fun(A &a) //也只能用指针或者引用
{
}
};
#endif
而在B.CPP中:
#include "B.h"
//在这里必须要包含A.h 才能实例化对象
#include "A.h"
B::B(void)
{
}
B::~B(void)
{
}
外围类需要使用嵌套类对象作为底层实现,并且该嵌套类只用于外围类的实现,且同时可以对用户隐藏该底层实现。
#include<iostream>
using namespace std;
class Outer
{
class Inter
{
public:
void Fun()
{
cout<<"Inner::fun..."<<endl;
}
};
public:
Inter obj_;
void Fun()
{
cout<<"Outer::Fun..."<<endl;
obj_.Fun();
}
};
int main(void)
{
Outer o;
o.Fun();
return 0;
}
从作用域的角度看,嵌套类被隐藏在外围类之中,该类名只能在外围类中使用。如果在外围类的作用域使用该类名时,需要加名字限定。
void Outer::Inter::Fun()
{
}
嵌套类的特点:
嵌套类中的成员函数可以在它的类体外定义。由上个例子可看到
嵌套类的成员函数对外围类的私有成员没有访问权,反之亦然。
嵌套类仅仅只是语法上的嵌套
如果嵌套类定义为共有的话,其实与外围类是一样的地位
局部类的特点:
q类也可以定义在函数体内,这样的类被称为局部类(loaclclass)。局部类只在定义它的局部域内可见。
q局部类的成员函数必须被定义在类体中。
q局部类中不能有静态成员
void Fun()
{
class LocalClass
{
public:
int num_;
void Init(int num)
{
num_ = num;
}
void Display()
{
cout<<num_<<endl;
}
};
//只能在函数内部可以使用
LocalClass lc;
lc.Init(10);
lc.Display();
}