- 知识点1【封装】
- 知识点2【类的初识】
- 知识点3【类的空间大小】
- 知识点4【在类内声明 类外定义 成员函数】
- 知识点5【类的定义在头文件 成员函数 在cpp文件中实现】
- 知识点6【构造和析构函数的概述】
- 知识点7【构造和析构函数的定义】
- 知识点8【构造函数的分类以及调用】
- 1、构造函数的分类
- 2、构造函数的调用
- 3、拷贝构造函数(系统提供一个拷贝构造函数 赋值操作)
- 4、拷贝函数的注意事项
- 知识点9【构造函数的调用规则】
- 把变量和函数合成一个整体,封装在一个类中
- 对变量和函数进行访问控制(公有、私有、保护)
| 访问属性 | 属性 | 对象内部 | 对象外部 |
|---|---|---|---|
| public | 公有 | 可访问 | 可访问 |
| protected | 保护 | 可访问 | 不可访问 |
| private | 私有 | 可访问 | 不可访问 |
在没有涉及继承与派生时,protected与private 是同等级的,外部不允许访问。
知识点2【类的初识】#include#include using namespace std; class Person{ private: char name[20];//定义类的时候,不要给成员初始化 int age; public: void setNmae(char* n){ strcpy(name,n); } char* getName(){ return name; } void setAge(int a){ age = a; } int getAge(){ return age; } }; int main(int argc, char *argv[]) { Person person; char name[20] = "tony"; person.setNmae(name); person.setAge(15); cout << person.getName() << person.getAge() << endl; return 0; }
实例:设计一个点和圆的类
#include知识点3【类的空间大小】using namespace std; class Point{//设计一个点的类 private: int m_x; int m_y; public: void setX(int x){ m_x = x; } int getX(){ return m_x; } void setY(int y){ m_y = y; } int getY(){ return m_y; } }; class Circle{//设计一个圆的类 private: Point point; int r; public: void setPoint(int x,int y){ point.setX(x); point.setY(y); } void setR(int x){ r = x; } void isPointOnCircle(Point &ob){ //判断点与圆的关系 int distance = (point.getX()-ob.getX()) *(point.getX()-ob.getX()) + (point.getY() - ob.getY()) * (point.getY() - ob.getY()); if(distance > r*r){ cout << "在圆外" << endl; }else if(distance == r*r){ cout << "在圆上" << endl; }else{ cout << "在圆内" << endl; } } }; int main(int argc, char *argv[]) { //实例化一个点对象 Point p1; p1.setX(5); p1.setY(5); //实例化一个圆对象 Circle circle; circle.setR(3); circle.setPoint(3,3); //判断点point与圆的关系 circle.isPointOnCircle(p1); return 0; }
成员数据占类的空间大小,成员函数不占类空间的大小。
using namespace std;
class Data
{
private:
//成员数据 占类的空间大小
int num;//4B
public:
//成员函数 不占类的空间大小
void setNum(int data)
{
num = data;
}
int getNum(void)
{
return num;
}
};
void test01()
{
printf("%dn",sizeof(Data));//4B
}
知识点4【在类内声明 类外定义 成员函数】
class data{
private:
int num;
public:
void setNum(int x);
int getNum();
};
void Data::setNum(int x){
num = x;
}
int Data::getNum(){
return num;
}
void test01(){
Data data;
data.setNum(100);
cout << data.getNum() << endl;
}
int main(int argc, char *argv[]){
test01();
return 0;
}
知识点5【类的定义在头文件 成员函数 在cpp文件中实现】
data1.h
#ifndef DATA1_H
#define DATA1_H
class Data1
{
private:
int num;
public:
void setNum(int x);
int getNum();
};
#endif // DATA1_H
data1.cpp
#include "data1.h"
void Data1::setNum(int x){
num = x;
}
int Data1::getNum(){
return num;
}
main.cpp
#include知识点6【构造和析构函数的概述】#include"data1.h" using namespace std; void test01(){ Data1 data; data.setNum(1000); cout << data.getNum() << endl; } int main(int argc, char *argv[]){ test01(); return 0; }
构造函数和析构函数都会被编译器自动调用,构造函数完成对象的初始化动作,析构函数在对象结束的时候完成清理工作。
注意:初始化和清理工作是编译器强制我们做的事情,即使程序并没有提供初始化操作和清理操作,编译器也会给程序增加默认的操作,但是默认操作并不会做任何事。
构造函数:实例化对象的时候系统自动调用
析构函数:对象释放的时候系统自动调用
构造函数的语法:
构造函数名与类名相同,没有返回类型,连void都不可以,但可以有参数,可以重载。
析构函数的语法:
析构函数的名字是在类名前面加“ ~ ”组成,没有返回类型,连void都不可以,不能有参数,不能重载。
案例:
#include知识点8【构造函数的分类以及调用】 1、构造函数的分类using namespace std; class Data { public: Data() { cout << "无参构造函数" << endl; } Data(int num){ num = 100; cout << "有参构造函数" << endl; } ~Data(){ cout << "析构函数" << endl; } }; int main(int argc, char *argv[]) { cout << "-----------01----------" << endl; Data ob; cout << "-----------02----------" << endl; return 0; }
按参数类型分类: 分为无参构造函数和有参构造函数
按类型分类:普通构造函数和拷贝构造函数(复制构造函数)
#includeusing namespace std; class Data { private: int num; public: Data() { num = 0; cout << "无参构造函数" << endl; } Data(int num1){ num = num1; cout << "有参构造函数" << num << endl; } ~Data(){ cout << "析构函数" << num << endl; } }; void test01(){ //调用无参或默认构造函数 Data ob; //调用有参构造函数(显式调用) Data ob1 = Data(100); //调用有参构造函数(隐式调用) Data ob2(1000); //隐式转换的方式 调用有参构造(针对于 只有一个数据成员)(尽量别用) Data ob3 = 10000;//转化成Data ob5(30) //匿名对象(当前语句结束 匿名对象立即释放) Data(40); cout << "---------------------" << endl; //千万不要 用以下方式调用 无参构造 //Data ob4();//不会被认为时实例化对象,会被看作函数ob4的声明 } int main(int argc, char *argv[]) { cout << "-----------01----------" << endl; test01(); cout << "-----------02----------" << endl; return 0; }
注意:在同一作用域,构造和析构的顺序相反(类似于栈,先进后出)
#includeusing namespace std; class Data { public: int num; public: Data() { num = 0; cout << "无参构造函数" << endl; } Data(int num1){ num = num1; cout << "有参构造函数" << num << endl; } //拷贝构造函数 Data(const Data &ob){//Data &ob = ob5; num = ob.num; cout << "拷贝构造函数" < cout << "析构函数" << num << endl; } }; void test01(){ //调用有参构造函数(隐式调用) Data ob3 = Data(100); cout<<"ob3.num = "< cout << "-----------01----------" << endl; test01(); cout << "-----------02----------" << endl; return 0; }
记住一句话:旧对象初始化新对象才会调用拷贝构造函数
Data ob1(10); Data ob2(ob1);//拷贝构造 Data ob3 = Data(ob1);//拷贝构造 Data ob4 = ob1;//拷贝构造函数
注意:下方就不会调用拷贝构造
Data ob1(10); Data ob2; ob2 = ob1;//不会调用拷贝构造 单纯对象 赋值操作
案例:
void test02(){
Data ob1 = Data(100);
Data ob2;
ob2 = ob1;
cout<<"ob1.num = "<
cout << "-----------01----------" << endl;
test02();
cout << "-----------02----------" << endl;
return 0;
}
4、拷贝函数的注意事项
(1)不能调用拷贝构造函数区初始化匿名对象
(2) 对象作为函数的参数 如果实参与形参都是普通对象 那么就会调用拷贝构造
(3)函数返回局部对象,在qt中会被优化,从而调用不了拷贝构造
系统默认会对任何一个类提供三个函数成员函数:
默认构造函数(空) 默认析构函数(空) 默认拷贝构造函数(浅拷贝)
1、如果用户提供了有参构造,将会屏蔽系统的默认构造函数
2、如果用户提供了有参构造,不会屏蔽系统的默认拷贝构造函数
3、如果用户提供了拷贝构造函数,将会屏蔽系统的默认构造函数和默认拷贝构造函数



