一.构造函数 和 析构函数
构造函数:创建对象时,用给定的值对对象进行初始化。
析构函数:释放对象
这两个函数可以由系统自己调用,不需要在构造对象时写出引用函数的语句
例子如下:
class Clock{
public:
Clock(int Newh,int Newm,int News); //构造函数
~clock(); //析构函数
void SetTime(int Newh,int Newm,int News);
Void ShowTime();
private:
int Hour,Minute,Second;
};
//构造函数的实现
Clock::Clock(int Newg,int Newm,int News){
//第一个Clock是类名,第二个clock是成员函数名
Hour=Newh;
Minute=Newm;
Second=News;
cout<<"Constructor called.\n";
}
Clock::~Clock(){
cout<<"Destructor called.\n";
}
//构造函数在main函数中的使用
int main(){
Clock c(0,0,0); //隐含调用构造函数,将初始值作为实参传入
c.ShowTime();
}
构造函数的特点:
- 函数名同类名
- 说明或定义构造函数是无需指出类型,也无返回值
- 构造函数是系统在创建对象时主动自己调用的
构造函数由于没有返回值而不能被继承,但可以被重载
析构函数的特点:
- 函数名与类名相同,在函数名前加“~”与构造函数区分
- 析构函数也是又系统自己调用的
- 析构函数定义不需类型,无返回值
析构函数由于没有参数而不能被重载
二.拷贝构造函数
拷贝构造函数:已知对象初始化,根据该对象初始化创建另一对象时使用的构造函数
//格式:
class //类名
{
public:
//类名(形参);//构造函数
//类名(类名 &对象名); //拷贝构造函数
};
/*
类名::类名(类名 &对象名)
{ 函数体 }
*/
//代码:
class Point {
public:
Point(int xx=0,int yy=0){
X=xx;
Y=yy;
}
Point(Point& P); //拷贝构造函数
int GetX(){
return X;
}
int Get(){
return Y;
}
private:
int X,Y;
}
//拷贝构造函数的代码实现
Point::Point(Point& p){
X=p.x;
Y=p.y;
}
如果没有定义拷贝构造函数,系统会自动创建一个默认拷贝构造函数
拷贝构造函数的调用
当用类的一个对象去初始化该类的另一个对象时系统自动调用拷贝构造函数
int main(){
Point A(1,2);
Point B(A); //调用拷贝构造函数,根据A构造B
cout<<B.GetX()<<endl;
}
若函数的形参为类的对象,调用函数时,实参赋值给形参,系统自动调用拷贝构造函数
void fun1(Point P){
cout<<P.GetX()<<endl;
}
int main(){
Point A(1,2);
fun(A);
}
当函数的返回值是类的对象时,系统自动调用拷贝构造函数
Point fun2(){
Point A(1,2);
return A; //返回对象A
}
int main(){
Point B;
B=fun2();
}
三.内联函数
内联函数是一种函数体被替换,而不是被调用的函数。功能简单需要反复使用的代码部分可以定义为内联函数。
在类中声明内联成员函数的方式:
- 将函数放在类的声明中
- 使用inline关键字
#include<iostream>
using namespace std;
class M{
public:
M(int i,int j){
a=i;
b=j;
}
int fun1(){
return a;
}
int fun2(){
return b;
}
int fun3(),fun4(); //内联函数声明
private:
int a,b;
};
//内联函数函数体
inline int M::fun3(){
return fun1()+fun2();
}
inline int M::fun4(_{
return fun3();
}
int main(){
M m(5,8);
int n=m.fun4();
cout<<n<<endl;
}
四.重载函数
成员函数可以重载,重载时应遵循参数可以区别的规则:
- 参数类型可区分
- 参数个数可区分
#include<iostream>
using namespace std;
class AB {
public:
AB(int i, int j) {
a = i;
b = j;
}
//重载
AB(int i) {
a = i;
b = i * i;
}
int Add(int x, int y);
//重载,根据参数个数区分
int Add(int x);
int Add();
int aout() {
return a;
}
int bout() {
return b;
}
private:
int a, b;
};
//成员函数代码实现
int AB::Add(int x, int y) {
a = x;
b = y;
return a + b;
}
int AB::Add(int x) {
a = b = x;
return a + b;
}
int AB::Add() {
return a + b;
}
int main() {
AB a(5, 8), b(7); //a调用AB(int i,int j),b调用AB(int i)
cout << "a=" << a.aout() << "," << a.bout() << endl;
cout << "b=" << b.aout() << "," << b.bout() << endl;
int i = a.Add(); //i=a+b=5+8
int j = a.Add(4); //j=a+b=4+4
int k = b.Add(3, 4); // k=a+b=3+4
cout << i << " " << j << " " << k << endl;
return 0;
}
设置参数的默认值
- 成员函数的参数可以设置为默认值
- 可以给一个或多个参数设置默认值
- 指定了默认值的参数的右边不能出现没有指定默认值的参数(会影响重载)
eg:
A(int i=8,int j=10,int k) 错误×
A(int i,int j=10,int k=9) 正确√
五.静态成员
静态成员可以解决数据共享的问题,在类中使用关键字static说明的成员称为静态成员包括:
- 静态数据成员
- 静态成员函数
静态成员不属于某个对象而属于整个类,静态成员的访问可以通过对象引用和类名引用。
5.1静态数据成员
说明方法如下:
class M{
int a,b,c;
static s; //静态成员
};
初始化:
数据类型 类名::数据成员名=初值;
访问方法如下:
类名 :: 静态数据成员名
//初始化
//类体外初始化
int M::s=0;
//访问方式
M::s;
静态成员必须在类体外初始化
5.2静态成员函数
静态成员函数格式:
static 类型 成员函数名(参数表);
静态成员函数的引用:
- 类名 :: 静态成员函数名(参数表);
- 对象名.静态成员函数名(参数表);
静态成员函数中可以直接引用其静态成员,而引用非静态成员则需针对对象,使用对象名引用。
#include<iostream>
using namespace std;
class Student{
public:
Student(char name1[],int sco){
......
}
void total(){
sum+=score;
count++; //非静态成员函数可以直接调用静态数据成员
}
static double aver(){
//静态成员函数
return (double) sum/count; //静态函数可以直接引用静态数据成员
}
private:
char name[20];
int score;
static int sum,count; //静态数据成员
}
};
int Student::sum=0;
int Student::count=0; //对静态数据成员初始化
int main(){
Student stu[5]={......};
for(int i=0;i<5;i++){
stu[i].total();
cout<<"Average="<<Student::aver()<<endl;
}
静态成员函数调用非静态数据成员:
class{
public:
static void F(A a); //静态成员函数
private:
int x; //非静态成员
};
void A::F(A a){
cout<<x; //错误的引用方式
cout<<a.x; //正确的引用方式 ,静态成员函数引用非静态数据成员要通过具体对象来引用
}
六.友元
6.1 友元函数
友元函数是说明在类体中的一般函数,不是类中的成员函数,但可以访问该类的所有成员。
友元函数说明格式: friend 类型 函数名(参数表)
友元说明在类体内,如被定义在类体外不加类名限定
class Point{
pbulic:
Point(double i,double j){
x=i;
y=j;
}
void Print(){
cout<<.....<<endl;
}
friend double Distance(Point a,Point b); //友元函数声明
private:
double x,y;
};
double Distance(Point a,Point b){
//类体外定义,无需类名,其他普通成员函数需要类名声明
double dx=a.x-b.x;
double dy=a.y-b.y;
return sqrt(dx*dy+dy*dy);
}
Point p1(d1,d2),p2(d3,d4);
double d=Distance(p1,p2); //友元调用同普通函数
友元函数可以访问类中的包括私有成员在内的全部成员,是一种破坏数据封装和数据隐藏的机制
6.2 友元类
若一个类为另一个类的友元,则此类的所有成员都能访问对方类的私有成员
声明格式: 将友元类在另一个类中用friend说明 friend class 类名
- 友元关系不可逆,A是B的友元不代表B也是A的友元
- 友元关系不可传递,B是A的友元,C是A的友元,B和C不一定是友元
class X{
friend class Y; //友元类声明
pbulic:
X(int i){
//构造函数
x=i;
}
void Print(){
cout<<"x="<<x<<","<<“s="<<endl;
}
private:
int x;
static int s; //静态成员
};
class Y{
pubilc:
Y(int i){
y=i;
}
void Print(X &r){
//调用类X中的数据成员
cout<<"x="<<r.x<<","<<"y="<<y<<endl;
private:
int y;
};