一、类
1.类的定义:
对具有相同属性和行为的一类客观事物的描述。是用户自定义的数据类型。
类包括行为(成员函数)和属性(数据成员)。
2.类的定义格式:
class 类名{
public://公有
protected://保护
private://私有
};//注意:此处分号不可以省略!!!!类定义以分号结束!
//举例:
class Student//类名见名知意,首字母大写
{
public:
void display();//成员函数一般为公有
private:
string name;
string id;
char sex;
int age;
double score;//数据成员一般为私有,类内使用,安全
};//注意分号结束
成员函数公有化;数据成员私有化
类以分号结束
注意:
(1)类的数据成员可以是其他类的对象,但不能以类自身的对象作为本类的成员,而类自身的指针和引用可以作为类的成员。
(2)类与结构体的区别:
没有明确指定类成员的访问权限时,C++结构体的成员都是公有的,而类的成员是私有的。
3.访问权限(控制)
public:公有成员,类的外部接口
protected:保护成员,仅允许本类成员函数及派生成员函数访问
private:私有成员,仅允许本类成员函数访问
4.成员函数
通过操纵数据成员,实现功能。成员函数可操作数据:1)类的数据成员。2)函数内定义的局部变量(包括形参)。3)成员函数(不建议使用,安全性不好)。
成员函数的定义:
返回值类型 类名::成员函数名(参数表)//表示该成员属于此类
{
函数体
}
举例:
class Point
{
public:
float getPointx();
float getPointy();//取得数据成员的值,数据成员本身不开放,通过公有get函数取得。另外,set函数设置数据成员值。
void initPoint(float PointA_x, float PointA_y); //初始
void move(float New_x, float New_y);
private:
float P1_x,P1_y;
};
void Point::InitPoint(float PointA_x, float PointA_y)
{
P1_x=PointA_x;
P1_y=PointA_y;
}
void Point::Move(float New_x, float New_y)
{//New表示偏移量
P1_x+=New_x;
P1_y+=New_y;
}
float Point::getPointx()
{
return P1_x;
}//取出数据成员的横坐标
float Point::getPointy()
{
return P1_y;
}
5.对象
对象是类的实例或者实体。
[对象(具体化),类(抽象)]
对象的定义格式:
类名 对象名1,对象名2,…,对象名n;
(先定义类,再定义对象。)
6.类成员的访问
对象成员的访问:
(1)对象名 . 公有成员
(2)指针访问形式:对象指针变量名->公有成员
举例:
#include<iostream.h>
class ptr_access {
public:
void setvalue(float a, float b) { x=a; y=b; }
float Getx() {return x;}
float Gety() {return y;}
void print()
{
cout<<"x="<<x<<endl;
cout<<"y="<<y<<endl;
}
private: //私有数据成员
float x,y;
};
int main()
{
float a1,a2;
ptr_access *ptr=new ptr_access;//
ptr->setvalue(2,8); //通过指针访问公有成员函数
ptr->print();
a1=(*ptr).Getx();
//两种方式,(对象名.公有函数)与(对象指针变量名->公有成员),通过公有成员函数访问私有数据成员
a2=(*ptr).Gety();
cout<<"a1="<<a1<<endl;
cout<<"a2="<<a2<<endl;
return 0;
}
例题:输入矩形的长和宽,输出面积和周长。
class CRectangle
{
public:
int w,h;
int Area() {
return w * h;
}
int Perimeter() {
return 2 * ( w + h);
}
void Init( int w_,int h_ ) {
w = w_; h = h_;//初始化
}
};
int main( )
{
int w,h;
CRectangle r; //r对象
cin >> w >> h;
r.Init( w,h);//成员函数操作需要从外部引用数据,则需要加形参;只对数据成员操作不加形参。
cout << r.Area() << endl << r. Perimeter();//调用
return 0;
}
成员函数操作需要从外部引用数据,则需要加形参;只对数据成员操作不加形参。
引入类就是引入数据类型,通过对象调用数据成员使用。
注意:
(1)在类的定义中不能对数据成员进行初始化。
(2)类的任何成员都必须指定访问属性,数据成员(private/protected),将成员函数(public)。
(3)类的成员可以是其他类的对象,称为类的组合。但不能以类自身的对象作为本类的成员。
7.内联函数:
作用: 减少频繁调用小子程序的运行的时间开销.
内联函数声明:
inline 函数原型
不能含有复杂结构控制语句 ,不能递归调用.
内联函数仅在函数原型作一次声明。
适用于只有1 ~ 5行的小函数.
8.重载:函数名相同,但参数(个数,类型)不同。
9.构造函数和析构函数
(1)构造函数:用于创建对象的特殊成员函数。
(2)构造函数的作用:为对象分配空间;对数据成员赋初值。
用户没有定义构造函数时,系统自动定义缺省的构造函数。
(3)
构造函数名与类名相同:类名
构造函数必须重载。
构造函数可以有任意类型的参数,但没有返回类型
(4)析构函数:用于取消对象的成员函数
(当一个对象作用结束时,系统自动调用析构函数,清理工作。用户没有定义析构函数时,系统自动定义缺省的析构函数)。
(5)析构函数的类名:~ 类名
析构函数没有参数,也没有返回值类型。
(6)默认构造函数:
类名::类名(){ }(无返回值类型,无参数)
构造函数创建对象有以下两种方法:
(a) 利用构造函数直接创建对象.其一般形式为:
类名 对象名[(实参表)];
不带参数:当用户没定义构造函数时,调用默认的构造函数;当用户定义了构造函数时,调用无参的构造函数(没有无参构造函数时要出错!系统不会调用默认构造函数)
带实参表:系统按照重载函数匹配原则,调用对应的构造函数;
构造函数时,一定要创建不带参数的构造函数。
#include<iostream>
using namespace std;
class Date{
public:
Date();//构造函数,一定要创建不带参数的
Date(int y,int m,int d);
void showDate();
private:
int year,month,day;
};
int year,month,day;
Date::Date()//构造函数的实现
{
year=0;month=0;day=0;
}
Date::Date(int y,int m,int d)
{
year=y;month=m;day=d;
}
inline void Date::showDate()
{
cout<<year<<"."<<month<<"."<<day<<endl;
}
int main(){
Date a,b(2020,3,15);
a.showDate();
b.showDate();
return 0;
}
(b)利用构造函数创建对象时,通过指针和new来实现。语法格式:
类名 *指针变量=new 类名[(实参表)]
eg:Date *date1=new Date(1999,4,24);创建了对象(*date1)
int main()
{
Date *date1;
date1=new Date(1998,4,28);
// 以上两条语句可合写成:Date *date1=new Date(1998,4,28);
cout<<"Date1 output1:"<<endl;
(*date1).showDate();
date1->showDate();
delete date1;
return 0;
}
构造函数初始化成员两种方式:
(1)使用构造函数的函数体进行初始化;
class Date
{
int d, m, y;
public:
Date(int dd, int mm, int yy)
{
d=dd;
m=mm;
y=yy;
}
Date()
{
d=0;
m=0;
d=0;
}
};
(2)使用构造函数的初始化列表进行初始化;
构造函数的初始化列表:
格式:
fun(参数列表):初始化列表
{函数体,可为空}
初始化列表的形式:
成员名1(形参名1),成员名2(形参名2),成员名n(形参名n)
class Date
{
int d, m, y;
public:
Date(int dd, int mm, int yy):d(dd),m(mm),y(yy)
{ }//数据成员d绑定形参dd
Date(): d(0),m(0),d(0)
{ }
};
必须使用初始化列表对数据成员进行初始化的几种情况:
1.数据成员为常量
2.数据成员为引用类型
3.数据成员为没有无参构造函数的类的对象
#include <iostream>
using namespace std;
class A{
public:
A(int i):x(i),rx(x),pi(3.14)//类名(形参):初始化列表
{}
void display()
{cout<<"x="<<x<<"rx="<<rx<<"pi="<<pi<<endl;}
private:
int x,℞//引用
const float pi;//常量
};
int main(){
A aa(10);
aa.display();
return 0;
}
#include <iostream>
using namespace std;
class A
{
public:
int a;
A(int x):a(x)
{
}
};//没有无参的构造函数的类
class B
{
private:
int b;
A aa;//类的数据成员在定义中不能初始化。数据成员为没有无参构造函数的类 的对象
public:
B(int x,int y):aa(x),b(y){}
void out()
{
cout<<aa.a<<endl<<b<<endl;
}
};
int main()
{
B bb(3,5);
bb.out();
return 0;
}
类成员的初始化顺序:
按照数据成员在类中的声明顺序,与初始化列表顺序无关。
#include <iostream>
using namespace std;
class CMyClass{
public:
CMyClass(int x, int y):m_y(x),m_x(m_y)
{
cout<<"m_x="<<m_x<<endl;
cout<<"m_y="<<m_y<<endl;
}
private:
int m_x,m_y;
};
int main()
{
CMyClass mc(15,10);
return 0;
}//运行结果:
m_x=-858993460随机值
m_y=15
析构函数
(最后调用)析构函数没有返回值,不能有参数,也不能重载
定义格式如下(类外实现):
类名::~类名()
{
函数语句
}
一般情况下,可以不定义析构函数
#include <iostream>
#include <string>
using namespace std;
class Student{
public:
Student(int n, string a_name, char s) {
num=n;
name=a_name;
sex=s; cout<<"Constructor called."<<endl;
}
~Student()
{ cout<<"Destructor called."<<endl; }
void display()
{cout<<name<<endl;cout<<num<<endl;cout<<sex<<endl; }
private:
int num; string name; char sex;
};