认识类
其内变量为成员变量,函数叫成员函数,有private,public,protected三种类型
#include<iostream>
using namespace std;
class student{ //student指代类名
private://隐私,除非通过公开内的访问,否则不可访问
public://公开,可以在结构外直接调用
student();//构造函数
student(char *, char *);
~student();//析构函数
void add();//若在类内定义函数,要在main函数内调用它,则要加上类名称去调用它,不加参数,可加数据类型
void add(double);//同名函数在cpp是允许的,运用括号内加数据类型区分
};
student::student(char *n1. char *n2)//定义了与类名一样的函数,需手动补充构造函数与析构函数
{
………………;
}
void a::add(int a,int b)//定义类内的函数要加上类名称及两个冒号
{
………………;
}
int main()
{
a.add(参数);//加上类名去调用它
return 0;
}
与struct的区别
class定义的内容默认为隐私的,struct默认为公开的
在c语言中,struct只能有成员变量,不能有成员函数,而cpp可以有成员函数
构造函数
使用指针时,用new会调用一次构造函数(函数名与类名相同的函数叫构造函数)
student();//构造函数,此构造函数是不带参数的
student(char *, char *);//一般如果不定义一个与类名一致的带参数的构造函数,系统会自动补充(缺省函数)此函数,但是若定义了,则需要手动补充上一个函数
析构函数
使用指针时,用delete会调用一次析构函数(~加构造函数叫析构函数),不能带参数!!!
~student();//析构函数
//当使用delete时,系统会在类内自动补充,但是若定义一个与类名一致的带参数的构造函数,则需要手动补充(缺省函数)此函数
类/结构的复合
在类私密成员内还有类,则必须进行初始化,否则程序会错误
若两个类内都有new,则delete时各自在类内用析构去除
在student类内无法访问date的私密成员
#inlude<iostream>
using namespace std;
struct date{
int y, m, d;
void setdate();
};
class student{ //student指代类名
private://隐私,除非通过公开内的访问,否则不可访问
date birthday;
int chinese;
public://公开,可以在结构外直接调用
student();//构造函数
student(char *, char *);
~student();//析构函数
void add();//若在类内定义函数,要在main函数内调用它,则要加上类名称去调用它,不加参数,可加数据类型
void add(double);//同名函数在cpp是允许的,运用括号内加数据类型区分
};
student::student(int y, int m, int d, int chinese)
:birthday(y, m, d),chinese(80)//当遇到类内有另外一个类或结构,可以用此方式为其内变量初始化
{
birthday.setdate(y, m, d);//也可以这样子初始化
}
int main()
{
student(y, m, d, chinese);
}
this指针
只能用于第一层类里面,在嵌套中不可使用它去调用第二层的类
class student{
private:
int x, y;
public:
student();
student(char *, char *);
~student();
void add();
void add(double);
};
void student::add(int x, int y)
{
this->x = x;
this->y = y;//this指针,当传入参数同名时可以用它进行区分
}
int main()
{
add(x,y)
}
拷贝构造函数
当发生类类型的变量发生参数传递时,会调用一次
#include<iostream>
using namespace std;
struct date{
int y, m, d;
void setdate();
};
class student{
private:
date birthday;
char *name;
public:
student(const student&);//系统会自行补,但是是浅拷贝;当当类内有new时,便要自己写一个深拷贝函数
student(char *, int, int, int);
~student(){delete []name;}
};
student::student(char *p, int y, int m, int d)
:birthday(y, m, d)
{
name = new char[srelen(p) + 1];
strncpy(name, p, strlrn(p));//括号内第一个为拷贝的目的地,第二个为要拷贝的东西,拷贝长度
}
student::student(const student &s)//此函数为深拷贝
:birthday(s.birthday)//将birthday初始化为s的birthday,此时会自动补拷贝构造函数
{
name = new char [strlen(s.name) + 1];
strncpy(name, s.name, strlen(s.name));
}
void print(student s)
{
………………
}
int main()
{
student(p, y, m, d);
print(s);//此时发生了类类型参数传递,故会调用拷贝调用函数,但是因为类内有new,所以要自己写一个深拷贝
return 0;
}
类的总结
-
因为利用类传递参数会引起构造函数与析构函数的调用,增加时间与空间复杂度,故而推荐用引用与指针传递参数或其他
-
无这种形式
//point是一个类,有x,y两个私密成员
point *p;
int x, y;
cin >> x >> y;
point *(p) (x, y);//这种形式是不行的,此函数为类内的构造函数
point p[1] (x, y);//这样子可以
//或者
p->setx(x)//setx(x)是类内的成员函数,这样子也可以,x,y分开设置即可
-
一般情况下不用实现拷贝构造函数,当类内有new时就一定要加
-
无论是定义还是函数返回值,使用一次类或结构时,都会调用一次构造函数和析构函数,指针与函数形参除外
静态static
-
可以定义成员变量,也可定义函数
-
静态函数没有this指针,而成员函数及构造函数都有this指针
-
调用静态函数的写法
#include<iostream> using namespace std; class Student { private: string age; int num; int age; static int count;//不属于任何一名同学,故定义成静态变量 static int totalAge;//不属于任何一名同学,故定义成静态变量 public: Student(string, int, int); void total(); static float averageAge();//无this指针,只能访问static定义的变量,其他成员变量不能访问 }; student::student(string name1, int num1, int age1) :name(name1),num(num1) { age = age1; } void Student::total() { totalAge += age; count++; } float Student::averageAge() { return totalAge*0.1/count; } int Student::count = 0; int Student::totalAge = 0;//静态成员变量需要初始化,格式像这样 int main() { Student::averageAge();//这样子调用 ……………… return 0; }
友元friend
当程序员将成员变量设置为私密时,未授权人员无法访问,增强了安全性。但当一定要访问时,可用友元。
- 可不是成员函数,不属于类
- 可以修改成员信息
- 可以设置其他类为friend**(注意!友元是单向的,在student内将date设置为friend。date可访问student的private,但是student不可以访问date的private【简单理解为我把你当朋友,你不把我当朋友】)**,也可设置其他类内单独函数
#include<iostream>
using namespace std;
calss date
{
private:
………………;
public:
function1;
function2;
};
class Student
{
private:
string age;
int num;
int age;
static int count;
static int totalAge;
public:
Student(string, int, int);
void total();
static float averageAge();
friend void print(Student * / Student &);//将参数设置为指针或引用,指向类的内容首地址,便可访问
friend function1;//设置其他类内函数为friend
friend class date;//设置其他类为friend
};
void print(Student &p)
{
cout << s.name
<< s.num
<<s.age;
}
int main()
{
………………
return 0;
}
小技巧
- 当遇到新创建的类内用到后创建的类,则可在其前先定义类
#include<iostream>
using namespace std;
class Student;//像这
class date
{
private:
………………;
public:
function1;//假设函数涉及到student,但是student在后面,放在前面student内也涉及到date,这时候便在前面提前定义
function2;
};
class Student
{
private:
string age;
int num;
int age;
static int count;
static int totalAge;
public:
Student(string, int, int);
void total();
static float averageAge();
friend void print(Student * / Student &);
friend function1;
friend date;
};
void print(Student &p)
{
cout << s.name
<< s.num
<<s.age;
}
int main()
{
………………
return 0;
}
在C++中,可以用const来定义一个const对象,但const对象不可以调用类中的非const成员函数
引发原因:: 由调用成员函数时隐式传入的当前对象的this指针引起。
- 非const成员函数中的隐式参数:classA* this
- const成员函数中的隐式参数:const classA* this
根本原因: - const对象的指针为const classA* this,因此传入非const成员函数时编译器报错(类型不匹配,无法从const 指针转换为非const指针);但传入const成员函数则类型匹配。
- 非const对象的指针为classA* this,可以调用const成员函数,因为const修饰符保证了不会修改该对象。
//错误形式
void print(const int* p);
//正确形式
void print(const int* p)const;