类的申明
class为定义类的关键字,ClassName为类名,{}中为类的主体,注意类定义结束时后面分号。
class ClassName{
//类的主体:由成员函数和成员变量组成
};
类的成员包括:
成员变量 | 成员函数 |
---|---|
类的属性 | 类的方法 |
使用类(class)描述:
①:class也可以用来描述对象类型,语法和struct几乎一致。
②:具有访问属性:public — 公有属性、protected — 受保护属性、 private — 私有属性。
③:因struct声明的类中的成员默认是公开的,class声明的类中成员默认是私有的。所以 在C++中一般不使用struct而使用class来声明类。
成员函数
class A{
public:
A() //无参构造函数
{
printf("construct !!!!!!!!!!!!\n");
}
A(int data) //有参构造函数
{
a = data;
}
~A() //析构函数
{
printf("dddddddddddddddddddddd\n");
}
void show() //成员函数
{
printf("------------------------\n");
}
void setdata(int data) //成员函数
{
a = data;
}
int getdata(void); //在类外定义成员函数
private:
int a; //数据成员
};
int A::getdata(void) //在类外定义成员函数
{
return a;
}
int main()
{
A x(100);//调用有参构造函数
// x.a = 100;
// x.setdata(100);
printf("%d\n",x.getdata());
x.show();
}
构造函数
- 构造函数的作用是初始化对象,处于类内部;
- 构造函数是一个特殊的函数,函数名和类名相同,没有返回值类型,可重载;
- 构造函数会在类构造对象时自动调用一次,在对象的生命周期内只调用一次。
- 构造函数必须是公有属性;
- 如果类没有构造函数,编译器在编译时会自动生成一个构造函数,这个构造函数什么都不做;
- 类应该提供构造函数。
拷贝构造函数
- 概念:拷贝构造函数是一个特殊的构造函数,当使用一个已经存在的对象去创建另一个同类型的新对象时会调用拷贝构造函数。
- 用法:
①:用已有的对象去构造新对象,例如: A a; A b = a; //拷贝构造;
②:把一个对象传递给同类型的形参;
③:把一个对象作为函数的返回值。 - 需要构造的情况:当对象内部存在独立内存时需要自定义拷贝,例如数组,指针等。
- 注意:
①:拷贝构造是将对象的数据逐字拷贝;
②:不同的对象不可以使用同一片内存,所以需要自定义拷贝函数;
③:系统默认的拷贝构造属于浅拷贝;为独立内存重新分配空间,拷贝空间中的内容叫深拷贝。
#include <stdio.h>
#include <string.h>
class A{
public:
A()
{
printf("A()\n");
p = new char[10];
strcpy(p,"hello");
}
A(const A &x)
{
printf("A (const A &x)\n");
p = new char[10];
strcpy(p,x.p);
}
~A()
{
printf("~A()\n");
delete [] p;
}
private:
char *p;
};
int main()
{
A x;
A y = x;
}
this指针
- 概念:
this指针在类内部的成员函数和构造函数中,代表调用该成员函数的对象或正在构造的对象。 - 使用方法:
① 可以在成员函数和构造函数中,使用this指针对重名的函数形参和成员变量做一个区分
② 可以作为成员函数的参数和返回值
③this指针是指向对象的,它代表对象的首地址。
析构函数
- 析构函数是一个特殊的函数,函数名和类名相同,但是前面要加一个~,参数列表为空,不可重载,也没有返回值;
- 析构函数在对象被销毁释放时会被自动调用一次;
- 如果类中没有析构函数,编译器会自动生成一个什么也不做的析构函数。
用法:如果在销毁对象时需要释放资源,比如动态内存在构造函数中申请了动态内存(new),在析构函数中使用(delete)。
常数据成员、常成员函数、常对象
C++推荐const而不用#define,mutable,const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的(static例外) 常数据成员(构造函数初始化表的方式赋值)
class A{
mutable int x; //修饰符,允许const函数修改
const int num; //const成员变量
public:
A(int n):num(n){....;} //初始化参数列表
void show(){.....} //普通成员函数
void show()const{.....} //const成员函数
};
A a;
const A b;//const对象
应用
①:const函数可以和同名的普通函数构成重载,非const对象优先调用非const函数,如果没有非const函数,再去调用const函数;
②:const对象只能调用 const函数,不能调用非const函数
③:const成员函数只能读取成员变量,不能修改成员变量,如果一定要修改,需要在声明成员变量时加mutable修饰。
静态成员
- 概念:
分为静态成员变量和静态成员函数。
①:静态成员变量:在声明时加static,必须初始化,且要在类外进行初始化。默认初始化为0,类类型调用默认的构造函数。
②:静态成员函数:在声明时加static,静态成员函数只能访问静态成员,不能访问非静态成员。 - 语法:
class A{
public:
int x;
static int num; //静态成员变量
static void show(){ //静态成员函数
//只能访问静态成员
//x = 100; //错误
}
};
int A::num = 100; //类外初始化
int main()
{
cout<<A::num<<endl; //静态成员属于类,所有对象共用同一片内存
A::show; //通过类名调用,但是用对象调用也不报错
return 0;
}
- 注意:
静态成员不需要通过对象访问,可以直接通过类名访问,静态成员属于类,而不属于某个对象。静态函数中没有this指针。静态成员具有以上性质的原因是它们存放在独立的内存中。
友元(破坏封装)
概念:
①:友元的作用就是让类外的数据突破访问权限的设置,友元可以访问类内任意数据;
②:可以将类/函数声明为某个类的友元,这些类和函数就可以访问类中的数据。
友元类:如果将类A声明为类B的友元,类A中就可以随问类B中的数据,不受访问属性的限制。
友元函数:友元函数是一个全局函数,在类内部可以将该函数声明为友元,这样这个全局函数就可以访问类内的数据。
友元成员函数
//友元函数:在类内部声明:
friend 函数声明;
//友元类:在类内部声明:
friend class 类名;
注意:
友元不受访问属性的限制,可以在类外访问类中的所有数据,破坏了累的封装属性,如非必要,不要使用。