C++ DAY03 类与对象

概述

对象:真实存在的事物 

类:

        多个对象抽取其共同点形成的概念
        静态特征提取出的概念称为成员变量, 又名属性
        动态特征提取出的概念称为成员函数, 又名方法
类与对象的关系
        在代码中先有类后有对象
        一个类可以有多个对象
        多个对象可以属于同一个类

类的定义

语法

class 类名
{
        [访问权限修饰符 :]
        成员变量
        成员函数
};

访问权限修饰符

private 私有的 , 当前类中可用 , 默认的
protected 受保护的 , 当前类或子类中可用
public 公共的 , 当前项目中可用

示例

class Person{
private:int age;
protected:char sex[10];
public:char name[50];void eat(){cout << name << "吃饭" << endl;}void sleep();
};
void Person::sleep()
{cout << name << "睡觉" << endl;
}

类的对象

概念

        类定义好之后, 可以通过类,创建具体的对象,创建的类的对象又称之为类的实例。
通过类创建的对象,对象即具有类的属性(数据)和方法         

语法

实例化对象
        类名 对象名;
操作其中的成员
        获取属性值
                对象名.属性名 ;
        修改属性值
                对象名.属性名 = ;
        调用函数
                对象名.函数名 ( 实参列表 );
注意 :
        以上对操作的成员, 必须在访问权限修饰符上得以满足
如在类外不能直接使用私有成员

示例

int main(int argc, char *argv[])
{
Person p1;
strcpy(p1.name,"张三");
p1.eat();
p1.sleep();
return 0;
}

封装性

即包装 , 将数据和方法封装在一起 , 加以权限区分使其可以保护内部 , 降低耦合度 , 便于使
int a = 10;
int nums[5] = {1,2,3,4,5};
void fun()
{xxx
}
class A
{属性函数
}
A a;
x.c
优点 :
        1,降低代码耦合度
        2,提高代码复用率
        3,编译使用

类的设计

1, 私有化所有属性
2, 提供可以获取这些属性值与修改属性值的函数

示例:

class Stu
{
private:char name[50];char sex[10];int age;
public:char* get_name(){return name;}void set_name(char* n){strcpy(name,n);}char* get_sex(){return sex;}void set_sex(char* s){strcpy(sex,s);}int get_age(){return age;}void set_age(int a){age = a;}void print_info(){cout << "姓名:" << name << "\t性别:" << sex << "\t年龄:" << age << endl;}
};
int main(int argc, char *argv[])
{Stu s;s.set_name("张三");s.set_sex("男");s.set_age(18);s.print_info();cout << s.get_name() << endl;cout << s.get_sex() << endl;cout << s.get_age() << endl;return 0;
}

构造函数

概念

构造函数 是类实例化对象的时候自动调用。
注意 :
        当一个类中没有构造函数, 系统将默认为其生成一个无参构造如果一个类中有构造函数, 系统将不会为其提供默认的无参构造一个类可以定义多个构造函数, 该类中的多个构造函数为重载关系
无参构造 :
        构造函数无形参列表
有参构造 :
        构造函数有形参列表

语法

类名 ( 形参列表 )
{
        该类对象赋初始值
}
注意 : 形参列表可有可无

示例

class Dog
{
private:char name[50];int age;
public:Dog(){cout << "调用无参构造" << endl;}Dog(char *n,int a){cout << "调用有参构造" << endl;strcpy(name,n);age = a;}Dog(char *n){cout << "调用一参构造" << endl;strcpy(name,n);}
};
int main(int argc, char *argv[])
{
//隐式调用无参构造创建对象
Dog d1;
//显式调用无参构造创建对象
Dog d2 = Dog();
//隐式调用有参构造创建对象
Dog d3("旺财",2);
//显式调用有参构造创建对象
Dog d4 = Dog("富贵",1);
//如果构造函数只有一个参数,会发生构造函数的隐式转换(知道就行)
//隐式转换
//类名 对象名 = 值;
Dog d5 = "黑豹";
//匿名对象:创建的对象没有对象名
Dog();
Dog("无名");
return 0;
}

析构函数

概念

对象生命周期结束的时候 自动调用析构函数。
注意 :
        一个类只能有一个析构函数
        如果用户不提供析构函数 编译器默认会提供一个空的析构函数。
经验 :
        一般不需要自定义析构函数, 但是如果类中有指针成员且指向堆区空间,这时必须实现析构函数, 在其中释放指针成员指向的堆区空间

语法

~ 类名 ()
{
}
注意 : 没有形参列表

示例

class Cat{
private:char name[50];
public:Cat(char *n){strcpy(name,n);cout << name << "被创建了" << endl;}~Cat(){cout << name << "被销毁了" << endl;}
};
void test01()
{Cat c("布丁");
}
int main(int argc, char *argv[])
{test01();return 0;
}

多对象构造与析构顺序

示例 1: 对象 A 与对象 B 平级 , 符合栈的顺序 ( 先进后出 ), 谁先创建谁后释放
class Cat{
private:char name[50];
public:Cat(char *n){strcpy(name,n);cout << name << "被创建了" << endl;}~Cat(){cout << name << "被销毁了" << endl;}
};
void test01()
{Cat c1("布丁");Cat c2("乔巴");{Cat c3("可乐");Cat c4("雪碧");}
}
int main(int argc, char *argv[])
{test01();return 0;
}

结果:

示例 2: 对象 A 是对象 B 的成员 , 先成员构造 , 在对象构造 , 在对象析构 , 在成员析构
class A{
public:
A(){cout << "A构造" << endl;
}
~A()
{cout << "A析构" << endl;
}
};
class B{
private:A a;
public:
B(){cout << "B构造" << endl;
}
~B()
{cout << "B析构" << endl;
}
};
int main(int argc, char *argv[])
{B b;return 0;
}

拷贝构造函数

概述

拷贝构造在以下情况自动触发 :
        1,旧对象给新对象初始化 , 会调用拷贝构造函数
        2,对象作为函数的形参 , 函数调用时会调用拷贝构造
        3,普通对象作为函数的返回值 (vs 会触发拷贝构造 ,Qt Linux 不会触发拷贝构造 )
注意 :
        如果用户不提供拷贝构造 编译器会提供一个默认的拷贝构造(浅拷贝)。
        只有类中有指针成员且指向堆区时 才有必要实现拷贝构造(深拷贝)。
浅拷贝与深拷贝
        浅拷贝: 当类中的成员有指针成员 , 此时只拷贝地址
        深拷贝: 当类中的成员有指针成员 , 先开辟内存 ,在拷贝其值        

语法

类名 (const 类名 &ob)
{
}

示例

示例 1: 旧对象给新对象初始化
class Cat{
private:
char name[50];
public:
Cat(char *n)
{
strcpy(name,n);
cout << name << "被创建了" << endl;
}
~Cat()
{
cout << name << "被销毁了" << endl;
}
Cat(const Cat &cat)
{
cout << "拷贝构造被调用了" << endl;
strcpy(name,cat.name);
}
};
int main(int argc, char *argv[])
{
Cat c1("布丁");
Cat c2 = c1;
return 0;
}
示例 2: 对象作为函数的形参 , 函数调用时会调用拷贝构造
class Cat{
private:char name[50];
public:Cat(char *n){strcpy(name,n);cout << name << "被创建了" << endl;}~Cat(){cout << name << "被销毁了" << endl;}Cat(const Cat &cat){cout << "拷贝构造被调用了" << endl;strcpy(name,cat.name);}
};
void test(Cat cat)
{
}
int main(int argc, char *argv[])
{Cat c1("布丁");test(c1);return 0;
}
示例 3: 普通对象作为函数的返回值 (vs 会触发拷贝构造 ,Qt Linux 不会触发拷贝构造 )
class Cat{
private:char name[50];
public:
Cat(char *n)
{
strcpy(name,n);
cout << name << "被创建了" << endl;
}
~Cat()
{
cout << name << "被销毁了" << endl;
}
Cat(const Cat &cat)
{
cout << "拷贝构造被调用了" << endl;
strcpy(name,cat.name);
}
};
Cat test()
{
Cat c1("布丁");
return c1;
}
int main(int argc, char *argv[])
{
Cat c = test();
return 0;
}

浅拷贝

class Cat{
public:
char *name;
Cat(char *n)
{
name = n;
cout << name << "被创建了" << endl;
}
~Cat()
{
cout << name << "被销毁了" << endl;
}
};
int main(int argc, char *argv[])
{
char name[10] = "Hi";
Cat c1(name);
Cat c2 = c1;
c2.name[0] = 'h';
cout << "c1.name = " << c1.name << endl;
cout << "c2.name = " << c2.name << endl;
return 0;
}

深拷贝

class Cat{
public:char *name;
Cat(char *n)
{name = (char *)calloc(1,50);strcpy(name,n);cout << name << "被创建了" << endl;
}
~Cat()
{cout << name << "被销毁了" << endl;free(name);
}
Cat(const Cat &cat)
{name = (char *)calloc(1,50);strcpy(name,cat.name);
}
};
int main(int argc, char *argv[])
{char name[10] = "Hi";Cat c1(name);Cat c2 = c1;c2.name[0] = 'h';cout << "c1.name = " << c1.name << endl;cout << "c2.name = " << c2.name << endl;return 0;
}

初始化列表

概述

构造函数 : 主要用于创建类的对象是给其属性赋初始值
在定义构造函数时, C++ 中提供了初始化列表的语法 , 以便于初始化成员变量的值。

语法

类名 ( 参数列表 ): 成员名 ( 参数名 ), 成员名 2( 参数名 2),... {
}

示例

示例1

class Data
{int a;int b;
public:
Data(int x,int y):b(y),a(x)
{
}
void print_data()
{cout << "a = " << a << endl;cout << "b = " << b << endl;
}
};
int main(int argc, char *argv[])
{Data d(10,1);d.print_data();return 0;
}

explicit关键字

作用

禁止隐式转换

语法

explicit 类名 ( 形参列表 ): 初始化列表
{
}

示例

class C{
private:
int a;
public:
explicit C(int x):a(x){}
};
int main(int argc, char *argv[])
{
C c = 10;//构造函数的隐式转换
//当调用构造函数使用explicit修饰后防止隐式转换,此时上述代码报错
return 0;
}

new与delete

情况 1: 操作基本类型
作用
new 申请堆区空间
delete 释放堆区空间。
示例:
void fun01()
{
int *p1 = new int;
*p1 = 100;
cout << *p1 << endl;
int *p2 = new int(100);//给p2的值初始化为100
cout << *p2 << endl;
}
情况 2: 操作数组
作用:
new 申请堆区空间
delete 释放堆区空间。
示例:
void fun02()
{
int *nums = new int[5];
cout << nums[0] << "\t" << nums[1] << endl;
delete [] nums;
int *ns = new int[5]{11,22,33,44,55};
cout << ns[0] << "\t" << ns[1] << endl;
delete [] ns;
}
情况 3: 操作对象
作用:
new: 分配空间 , 调用构造函数
delete: 调用析构函数 , 释放空间
示例:
class D{
public:
D(){
cout << "D构造" << endl;
}
~D(){
cout << "D析构" << endl;
}
};
void fun03()
{
D *d = new D();
delete d;
}

注意:

malloc,calloc,free 只能申请或释放空间 , 不能调用构造函数或析构函数
new,delete, 既能申请或释放空间 , 又能调用构造函数或析构函数
所以建议不要使用 malloc,calloc,free 等函数了

对象数组

静态对象数组
示例:
class A
{
public:
int mA;
public:
A()
{
cout<<"A无参构造"<<endl;
}
A(int a)
{
mA = a;
cout<<"A有参构造mA="<<mA<<endl;
}
~A()
{
cout<<"A析构函数mA="<<mA<<endl;
}
};
void fun04()
{
//对象数组 必须显示调用构造函数初始化
A arr[5]={A(10),A(20),A(30),A(40),A(50)};
int n = sizeof(arr)/sizeof(arr[0]);
int i=0;
for(i=0;i<n;i++)
{
cout<<arr[i].mA<<" ";
}
cout<<endl;
}
动态对象数组
示例:
void fun05()
{
A *arr = new A[5]{A(10),A(20),A(30),A(40),A(50)};
int i=0;
for(i=0;i<5;i++)
{
cout<<arr[i].mA<<" ";
}
cout<<endl;
//delete arr;//只会释放第0个元素
delete [] arr;
}

静态成员

静态成员变量
概述:
        static修饰的成员为静态成员。
特点 :
        静态成员是属于类而不是对象。(所有对象共享)
注意 :
        静态成员数据不占对象的内存空间。
        静态成员数据是属于类 而不是对象(多有对象共享一份静态成员数据)
        静态成员数据在定义对象之前就存在。静态成员数据在类中定义, 类外初始化。
示例:
class E{
public:
static int num;//类中定义静态成员
};
int E::num = 100;
int main(int argc, char *argv[])
{
//使用类名访问
cout << "E::num = " <<E::num << endl;
E e1;
E e2;
//使用对象名访问
cout << "e1.num = " <<e1.num << endl;
cout << "e2.num = " <<e2.num << endl;
e1.num = 1;
//一个对其修改该类所有对象的静态成员都将被修改
cout << "E::num = " <<E::num << endl;
cout << "e1.num = " <<e1.num << endl;
cout << "e2.num = " <<e2.num << endl;
return 0;
}

静态成员函数

概述:

使用 static 修饰的成员函数
特点 :
静态成员函数只能访问静态成员数据
示例:
class E{
private:
static int num;//类中定义静态成员
int x;
public:
static void set_num(int n)
{
num = n;
cout << "静态函数set_num被执行" << endl;
}
static int get_num()
{
cout << "静态函数get_num被执行" << endl;
return num;
}
};
int E::num = 100;
int main(int argc, char *argv[])
{
//使用类名调用
E::set_num(10);
int x = E::get_num();
//使用对象调用
E e;
e.set_num(1);
return 0;
}

单例模式

概述
所属的类 只能实例化一个对象。
示例 : 懒汉式
class DL{
private:
static DL *dl;
DL(){}
DL(const DL &d){}
public:
int x;
static DL* get_instance()
{
if(dl == NULL)
{
dl = new DL();
}
return dl;
}
};
DL *DL::dl = NULL;
int main(int argc, char *argv[])
{
DL *d1 = DL::get_instance();
DL *d2 = DL::get_instance();
DL *d3 = DL::get_instance();
d1->x = 1;
d2->x = 10;
d3->x = 100;
cout << "d1.x = " << d1->x << endl;
cout << "d2.x = " << d2->x << endl;
cout << "d3.x = " << d3->x << endl;
return 0;
}
示例 : 饿汉式
class DL{
private:
static DL *dl;
DL(){}
DL(const DL &d){}
public:
int x;
static DL* get_instance()
{
return dl;
}
};
DL *DL::dl = new DL();
int main(int argc, char *argv[])
{
DL *d1 = DL::get_instance();
DL *d2 = DL::get_instance();
DL *d3 = DL::get_instance();
d1->x = 1;
d2->x = 10;
d3->x = 100;
cout << "d1.x = " << d1->x << endl;
cout << "d2.x = " << d2->x << endl;
cout << "d3.x = " << d3->x << endl;
return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/155949.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

shell脚本之条件语句

条件语句 linux测试 test 测试 测试表达式是否成立&#xff08;用echo $? 检测是否正确&#xff09; 语法&#xff1a;test [选项] [文件名] 选项作用-e测试文件是否存在-r查看文件有无读的权限-d测试是否为目录-f测试是否为文件-w测试当前用户有无写的权限-x测试是否有执…

香港科技大学广州|机器人与自主系统学域博士招生宣讲会—同济大学专场!!!(暨全额奖学金政策)

在机器人和自主系统领域实现全球卓越—机器人与自主系统学域 硬核科研实验室&#xff0c;浓厚创新产学研氛围&#xff01; 教授亲临现场&#xff0c;面对面答疑解惑助攻申请&#xff01; 一经录取&#xff0c;享全额奖学金1.5万/月&#xff01; &#x1f559;时间&#xff1a;…

git使用及常用命令

在初入公司中&#xff0c;若使用的是git管理工具&#xff0c;需要做以下步骤&#xff1a; 1&#xff0c;常用命令在&#xff1a; &#xff08;1&#xff09;&#xff0c;git config --global user.name xxx(名字) //若不设置 那么下次提交代码时会报错 其次该设置名字和…

gitlab安装配置及应用

安装 ##安装依赖 yum install -y curl policycoreutils-python openssh-server perl#上传包 rz gitlab-jh-16.5.2-jh.0.el7.x86_64.rpm 安装 yum install gitlab-jh-16.0.3-jh.0.el7.x86_64.rpm 初始化并启动 # 以下两种方法都可以配置访问地址&#xff0c;第一种需要在yum安…

深度学习之二(前馈神经网络--Feedforward Neural Network)

概念 前馈神经网络(Feedforward Neural Network)是一种最基本的神经网络结构,也被称为多层感知器(Multilayer Perceptron,MLP)。它的特点是信息只在网络中单向传播,不会形成环路。每一层神经元的输出都作为下一层神经元的输入,没有反馈回路。 结构: 前馈神经网络通…

小程序中打印机纸张都支持哪些尺寸?

在小程序中添加打印机功能是一项非常实用的功能&#xff0c;它可以让用户方便地将小程序中的内容打印出来。然而&#xff0c;当用户想要打印内容时&#xff0c;他们可能会关心打印纸张支持哪些尺寸。打印机分为四种打印机&#xff1a;小票、标签、发货单和电子面单。下面具体介…

YOLO改进系列之注意力机制(GatherExcite模型介绍)

模型结构 尽管在卷积神经网络&#xff08;CNN&#xff09;中使用自底向上的局部运算符可以很好地匹配自然图像的某些统计信息&#xff0c;但它也可能阻止此类模型捕获上下文的远程特征交互。Hu等人提出了一种简单&#xff0c;轻量级的方法&#xff0c;以在CNN中更好地利用上下…

使用VC++设计程序,进行全局固定阈值分割、自适应阈值分割

图像分割 获取源工程可访问gitee可在此工程的基础上进行学习。 文章目录 图像分割实验内容一、全局固定阈值分割全局固定阈值分割的原理全局固定阈值分割的实验代码全局固定阈值分割的实验现象 二、自适应阈值分割自适应阈值分割的实验原理自适应阈值分割的实验代码自适应阈值…

解决 urllib2 中 CookiesMiddleware 的 cookie 问题

1. 问题背景 在网络爬虫开发中&#xff0c;Cookie 是一项关键的技术&#xff0c;用于跟踪用户的身份和状态。Cookie 是服务器在客户端存储的数据&#xff0c;通常用于维护用户会话和保存用户的登录信息。在爬虫应用中&#xff0c;模拟用户行为和保持 Cookie 状态是必要的&…

51单片机应用

目录 ​编辑 1. C51的数据类型 1.1 C51中的基本数据类型 1.2 特殊功能寄存器类型 2. C51的变量 2.1 存储种类 1. C51的数据类型 C51是一种基于8051架构的单片机&#xff0c;它支持以下基本数据类型&#xff1a; 位&#xff08;Bit&#xff09;&#xff1a;可以表…

超级实用的程序员接单平台,看完少走几年弯路,强推第一个!

”前途光明我看不见&#xff0c;道路曲折我走不完。“ 兜兜转转&#xff0c;心心念念&#xff0c;念念不忘&#xff0c;必有回响。终于找到了....... 网络上好多人都在推荐程序员线上接单&#xff0c;有人说赚得盆满钵满&#xff0c;有的人被坑得破口大骂&#xff0c;还有的人…

STM32踩坑:LAN8720未接网线,上电后再接网线,网络模块无法正常使用

LAN8720未接网线&#xff0c;上电后再接网线&#xff0c;网络模块无法正常使用 一、问题描述 最近因为做的项目出了BUG&#xff0c;STM32 单片机在未接网线的状态下&#xff0c;上电一段时间后&#xff0c;将网线插入网口后&#xff0c;IP地址ping不通&#xff0c;网络模块无…

XDAG同步节点部署

系统环境要求 JDK : v17 Maven : v3.9.1-v3.9.5 MySQL : v8.0系列 1、MySQL8.0安装 1&#xff09;docker-compose安装详情 MySQL安装 2&#xff09;配置数据库账号密码及键表 # docker exec -it mysql8 /bin/bash # root0286a1fd60e6:/# mysql -uroot -p Enter password:…

【Echart】Echart设置label太长隐藏:

文章目录 第一种&#xff1a;竖排显示第二种&#xff1a;显示部分第三种&#xff1a;强制显示所有标签并旋转 第一种&#xff1a;竖排显示 xAxis: {type: category,data: res.data.data.sz.xAxis,axisLabel:{fontSize:12,formatter: function(value) {return value.split().joi…

线程池有几种创建方式?

程序员的公众号&#xff1a;源1024&#xff0c;获取更多资料&#xff0c;无加密无套路&#xff01; 最近整理了一波电子书籍资料&#xff0c;包含《Effective Java中文版 第2版》《深入JAVA虚拟机》&#xff0c;《重构改善既有代码设计》&#xff0c;《MySQL高性能-第3版》&…

人员定位系统人员聚集风险监测预警功能为企业安全生产保驾护航!

危化企业生产区域由于装置设施开停工、设备检维修或其它原因&#xff0c;会导致在局部作业区域出现作业操作人员、指挥管理人员不定时、不定点的聚集情况&#xff0c;一旦发生泄漏中毒、火灾爆炸、高温高热物质喷溅等事故&#xff0c;人员聚集将会在一定程度上加重事故后果的严…

【测试开发】学习测试前的基础知识

文章目录 目录 前言 一、什么是软件测试 二、软件测试的发展史 三、软件测试和研发的区别 四、测试人员应该具备的能力 五、测试所需要知道的基本概念 1.需求 六、软件错误&#xff08;BUG&#xff09;的概念 前言 本篇文章主要讲解在学习测试前一些需要了解的知识。 一、什…

2023年【A特种设备相关管理(锅炉压力容器压力管道)】模拟考试题及A特种设备相关管理(锅炉压力容器压力管道)作业考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 A特种设备相关管理&#xff08;锅炉压力容器压力管道&#xff09;模拟考试题参考答案及A特种设备相关管理&#xff08;锅炉压力容器压力管道&#xff09;考试试题解析是安全生产模拟考试一点通题库老师及A特种设备相关…

【优秀毕设】基于vue+ssm+springboot的网上购物商城系统设计

摘 要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;网上商城购物系统当然也不能排除在外。网上商城购物系统是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方…

物联网AI MicroPython学习之语法 PWM脉宽调制模块

学物联网&#xff0c;来万物简单IoT物联网&#xff01;&#xff01; PWM 介绍 模块功能: PWM脉宽调制驱动模块 接口说明 PWM - 构建PWM对象 函数原型&#xff1a;PWM(ch, freq, duty)参数说明&#xff1a; 参数类型必选参数&#xff1f;说明chobjectYPin对象例如&#xf…