1. 类的定义
类是对具有相同属性和行为的一组对象的抽象与统一描述。是用户自定义的数据类型
●类的定义包括行为和属性两个部分。
● 属性以数据表示,行为通过函数实现。
2。类的表现形式
class 类名 //除class外还有struct,区别是struct所有成员都是公有的。
{
public:
公有数据成员和成员函数;
protected:
保护数据成员和成员函数;
private:
私有数据成员和成员函数;
}; //冒号不能省略。
各成员函数的实现
class Student //定义学生类Student
{
public: //声明类成员
void Getinfo(string pname, string pid
,char Sex, int a,double s);
void modify(float s);
void display();
private:
string name;
stringid;
char sex;
int age;
double score;
}; //类定义以分号结束
注意:1. 类与结构体相比是具有封装性的,是指没有明确指定类成员的访问权限时,C++结构体的成员是公有的,而类的成员是私有的。
2. 类的成员可以是其他类的对象,结构,数组,类等,但不能以类自身的对象作为本类的成员。
class student
{
char name[10];
date birthday;
long code;
char *address;
char phone[20];
//····
};
● Public 公有成员,类的外部接口,在类内外可以访问
● Protected 保护成员,仅允许本类成员函数及派生类成员函数访问
● Private 私有成员,仅允许本类成员访问
4.成员函数
定义:
类的成员函数是实现类的行为属性一般将成员函数声明为函数原型,在类外具体实现成员函数。
形式表现:
返回值类型 类名::成员函数名(参数表)
{
函数体
}
class Point
{
public:
float GetPointx();
float GetPointy();
void InitPoint(float PointA_x, float PointA_y);
private:
float P1_x,P1_y;
void Point::InitPoint(float PointA_x, float PointA_y)
{
P1_x=PointA_x;
P1_y=PointA_y;
}
}
//····
public:
void setdate(int y,intm,int d)
{ year=y;
month=m;
day=d;
}
●指针访问形式 :对象指针变量名—>公有成员
#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(); return 0;
}
7.成员函数重载
函数重载:函数名相同,但参数不相同(类型不同,或者个数不同)的一组函数。 编译器根据不同参数的类型和个数产生调用匹配。 函数重载用于处理不同数据类型的类似任务。
1.构造函数和析构函数
① .构造函数定义:构造函数是用于创建对象的特殊成员函数。当创建对象时,系统自动调用构造函数
构造函数的作用是: 为对象分配空间;对数据成员赋初值;请求其他资源。
② 析构函数定义:析构函数是用于取消对象的成员函数。当一个对象作用域结束时,系统自动调用析构函数。
析构函数的作用是:进行对象消亡时的清理工作。
③ 注意:没有用户定义的构造函数时,系统提供缺省版本的构造函数。构造函数名与类名相同。构造函数可以重载。构造函数可以有任意类型的参数,但没有返回类型。构造函数在建立对象时自动调用。没有用户定义析构函数时,系统提供缺省版本的析构函数。 析构函数没有参数,也没有返回类型。
④ 构造函数和析构函数的原型:
类名::类名(参数表);
类名::~类名();
Date::Date(int y,int m,int d)
{ year=y; month=m; day=d; }
Date::~Date()
{ cout<<”date object initializad/n”;}
注意:构造函数和析构函数不应定义在私有部分。
⑤ 构造函数组成分为带参构造函数和默认构造函数;如果类中没有定义构造函数,系统将自动生成一个默认形式的构造函数,用于创建对象,默认构造函数是一个空函数。
class Date {
public:
Date(); /
Date(int y,int m,int d);
Void Set Date(int m,int n,int t);
void showDate();
private:
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; }
Void Date::setDate(int m,int n,int t)
{year=m; day=t; month=n;}
注意;Date::Date()和Date::SetDate()的区别是SetDate可以多次重置数据成员的值,构造函数仅用于创建对像和数据初始化。
⑥ 构造函数创建对象的两种方法:
v 利用构造函数直接创建对象:date.date(1998,4,28);
v 利用构造函数创建对象时,通过指针和new来实现。 类名 *指针变量 = new 类名[(实参表)];Date *date1=new Date(1998,4,28);构造函数的初始化列表
v 使用构造函数的函数体进行初始化 Date(int dd, int mm, int yy)
{
d=dd;
m=mm;
y=yy;
}
v .使用构造函数的初始化列表进行初始化
funname(参数列表):成员1(形参名1),成员名2(形参名2),成员名n(形参名n)
{ 函数体,可以是空函数体 }
Date(int dd, int mm, int yy):d(dd),m(mm),y(yy)
{ }
注意:必须使用参数初始化列表对数据成员进行初始化的情况:
数据成员为常量。数据成员为引用类型。数据成员为没有无参构造函数的类的对象。
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;
类成员的初始化的顺序:
按照数据成员在类中的声明顺序进行初始化,与初始化成员列表中出现的顺序无关
#include <iostream>
using namespace std;
class CMyClass{
public:
CMyClass(int x, int y):m_y(x),m_x(m_y) //与初始化列表顺序无关,先赋值的是 x后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;
}
2. 构造函数的重载
构造函数可以具有默认参数。定义构造参数时,注意调用时可能产生的二义性
class Box
{public:
Box();
Box(int ,int , int);
private:
int height,width, length;};
Box::Box(){ height=10; width=10; length=10;}
Box::Box(int h, int w,int l):height(h),width(w),length(l){}
int main()
{ Box box1;
cout<<"The volume is "<<box1.volume();
Box box2(12,30,25);
cout<<"The volume is "<<box2.volume();
return 0;
}
构造函数一般被定义为公有成员。一般情况下,可以不定义析构函数但如果类的数据成员中包含指针变量是从堆上进行存储空间分配的话,需要在析构函数中进行存储空间的回收
3.this 指针用来指向不同的对象。
引用this的三种情况:
(1)在类的非静态成员函数中返回类对象本身或对象的引用的时候,直接使用 return *this,返回本对象的地址时,return this。
(2)当参数与成员变量名相同时,如this->x = x,不能写成x = x。
(3)避免对同一对象进行赋值操作,判断两个对象是否相同时,使用this指针。
class Person{
public:
Person(string n, int a) {
name = n; //这里的 name 等价于this->name
age = a; //这里的 age 等价于this->age
}
int get_age(void) const{ return age; }
Person& add_age(int i) {age += i; return *this; }
private:
4.复制构造函数
形式:类名 :: 类名(const 类名 & 引用名 , …)
注意:
public:
Box(int =10, int =10, int =10);
Box(const Box & b) //形成一个类b,然后将b复制成box
{height=2*b.height; width=2*b.width;length=2*b.length;}
int volume();
private:
int length, height, width;
};int main(){
Box box1(1,2,3),box2(box1),box3=box2;} //两种复制形式
- 声明语句中用类的一个已知对象初始化该类的另一个对象时。
- 当对象作为一个函数实参传递给函数的形参时,需要将实参对象去初始化形参对象时,需要调用复制构造函数。
- 当对象是函数的返回值时,由于需要生成一个临时对象作为函数返回结果,系统需要将临时对象的值初始化另一个对象,需要调用复制构造函数。
6.浅复制和深复制
浅复制:
●在用一个对象初始化另一个对象时,只复制了数据成员,而没有复制资源,使两个对象同时指向了同一资源的复制方式。
即:对于复杂类型的数据成员只复制了存储地址而没有复制存储内容。默认复制构造函数所进行的是简单数据复制,即浅复制
●通过一个对象初始化另一个对象时,不仅复制了数据成员,也复制了资源的复制方式称为深复制。
在类的成员函数说明后面可以加const关键字,则该成员函数成为常量成员函数
注意:
int k;
const int M;
Mclass() : M(5) { }
void testFun()
{ //M++; //不能在成员函数中修改常数据成员
k++; //可以修改一般数据成员
k++;
}
用带参数的构造函数初始化常数据成员
public: Student (int y,int m,int d, int num=0, sring name="no name"); void PrintStudent()const; //常成员函数 private: const int code; //常数据成员 string name; Date birthday; //结构数据成员 };
Student::Student( int y, int m, int d, int num, string name ) : code( num )
2常对象
如果在说明对象时用const修饰,则被说明的对象为常对象。
常对象的说明形式如下:
类名 const 对象名[(参数表)];
或者
const 类名 对象名[(参数表)];
3.常成员函数
类型说明符 函数名(参数表) const;
const是函数类型的一个组成部分,因此在函数的实现部分也要带关键字const。
常成员函数不能更新对象的数据,也不能调用非const修饰的成员函数(静态成员函数、构造函数除外)
class Simple
{ int x, y ;
public :
void setXY ( int a, int b) { x = a ; y = b ; }
void printXY() { cout << x << "," << y << endl ; }
void constFun ( ) const
{ x ++ ; y ++ ; }//非法
};
静态成员不属于某一个单独的对象,而是为类的所有对象所共有。它的作用不是为了对象之间的沟通,而是为了能处理静态数据成员: 保证在不依赖于某个对象的情况下,访问静态数据成员
class A
{
int n;
static int s;
};
注意:
类型 类名::静态数据成员[=初始化值]; 不能在成员初始化列表中进行初始化。如果未进行初始化,则编译器自动赋初值(默认值是0)。初始化时不能使用访问权限
静态函数仅可以访问静态成员,或是静态成员函数或是静态数据成员。
1.友元函数
友元函数(函数B)可以访问这个类(类A)中的私有成员
class A
{ private:
int i ;
friend void FriendFun(A * , int) ;
public:
void MemberFun(int) ;
} ;
…
void FriendFun( A * ptr , int x )
{ ptr -> i = x ; }
当一个类中含有已经定义的类类型成员,带参数的构造函数对数据成员初始化,须使用初始化语法形式。
构造函数 ( 形参表 ) : 对象成员1(形参表 ) , … , 对象成员n (形参表 ) ;
{ public:
B( int x, int y ) : aa(x) { b = y ; }
void out() { cout<<"aa = "<<aa.a<<endl<<"b = "<<b<<endl ; }
private:
int b ;
A aa ;
} ;
所谓对象数组是指每一数组元素都是对象的数组。 类名 数组名[下标表达式];
int main(){
Point p1[4];
Point p2[4]={5,6,7,8};
Point p3[4]={Point(9,10),Point(11,12),Point(13,14),Point(15,16)};
Point p4[4]={Point(17,18),Point(10,20)};
Point p5[2][2]={21,22,Point(23,24)};
}
Point p1[4];
p1[0]=Point(1,1);
}
个人心得: