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.mfbz.cn/a/167888.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HashMap会用就行了?一文解决HashMap的底层问题

前言 我们的手机通讯录之所以能快速定位到特定联系人&#xff0c;就是因为它运用了HashMap底层的原理。手机通讯录将每个联系人的姓名作为键&#xff0c;电话号码作为对应的值&#xff0c;通过这个键值对的方式实现了快速的数据定位和获取。就像你通过关键字快速找到对应的联系…

vue动态配置路由

文章目录 前言定义项目页面格式一、vite 配置动态路由新建 /router/utils.ts引入 /router/utils.ts 二、webpack 配置动态路由总结如有启发&#xff0c;可点赞收藏哟~ 前言 项目中动态配置路由可以减少路由配置时间&#xff0c;并可减少配置路由出现的一些奇奇怪怪的问题 路由…

你学了Python之后让你成为行业卷王,升职加薪更有优势

都说Python能够实现自动化&#xff0c;那么Python具体能应用在哪些地方?哪些岗位学了Python更有优势?今天我们来看看一些大神将Python应用的出神入化的成果。 在这之前&#xff0c;先跟为大家分享个真实的故事。我朋友小宇前段时间为了一个品牌设计的大项目&#xff0c;想方案…

Elasticsearch 和 LangChain 合作开发可用于生产的 RAG 模板

作者&#xff1a;Aditya Tripathi 在过去的几个月里&#xff0c;我们一直与 LangChain 团队密切合作&#xff0c;他们在推出 LangServe 和 LangChain 模板方面取得了进展&#xff01; LangChain Templates 是一组用于构建生产质量的生成式 AI 应用程序的参考架构。 你可以在此处…

QMI8658A Datasheet Rev A-勘误表

QMI8658A Datasheet Rev A-勘误表 1. Reset Register2. CTRL9 Command List3. Temp Sensor Output 1. Reset Register 在5.9章节 和 7.4 章节对复位操作的写入数据&#xff0c;有笔误 正确的数据是&#xff1a; 0xB0 2. CTRL9 Command List 在 5.10.2 章节 Table 28. List…

汇编-loop循环指令

LOOP指令是根据ECX计数器循环&#xff0c;将语句块重复执行特定次数。 ECX自动作为计数器&#xff0c; 每重复循环一次就递减1。 语法如下所示&#xff1a; 循环目的地址必须在距离当前位置计数器的-128到127字节范围内 LOOP指令的执行有两个步骤&#xff1a; 第一步&…

SpringBoot的启动流程

一、SpringBoot是什么&#xff1f; springboot是依赖于spring的&#xff0c;比起spring&#xff0c;除了拥有spring的全部功能以外&#xff0c;springboot无需繁琐的xml配置&#xff0c;这取决于它自身强大的自动装配功能&#xff1b;并且自身已嵌入Tomcat、Jetty等web容器&am…

GreatSQL社区与Amazon、Facebook、Tencent共同被MySQL致谢

一、来自MySQL官方的感谢 在 2023-10-25 MySQL 官方发布的 8.2 版本 Release Notes 中&#xff0c;GreatSQL 社区核心开发者 Richard Dang 和 Hao Lu &#xff0c;分别收到了来自 MySQL 官方的贡献感谢&#xff0c;与Amazon、Facebook(Meta)、Tencent等一并出现在感谢清单中。…

2023年电子工程师大会暨第三届社区年度颁奖活动--【其利天下技术】

华秋电子发烧友将于2023年11月23日在深圳举办一场盛大的技术交流活动&#xff0c;即“2023年电子工程师大会暨第三届社区年度颁奖活动”。本次活动邀请了各大高校教授、企业高管、行业专家和电子工程师们齐聚一堂&#xff0c;围绕“开源硬件”、“OpenHarmony RISC-V”、“工程…

【技术指南资料】编码器与正交译码器

我想提出一个关于PicoScope7新的译码器功能讨论。它已经推出一段时间&#xff0c;但你可能不知道这在汽车领域是扮演相当重要的角色。 正交译码器被用在转子位置传感器来转换关于旋转轴角度及方向的信息。 举例来说&#xff0c;它在电机上采用一对二进制的信号型式。 这种传感器…

C#的类型转换

目录 一、简介二、基本类型转换1.整数类型转换1.隐式转换2.显式转换 2.浮点类型转换1.隐式转换2.显式转换 3.字符类型转换1.字符到整数的转换2.整数到字符的转换 4.布尔类型转换1.布尔到整数的转换2.整数到布尔的转换 三、隐式转换和显式转换四、装箱和拆箱五、自定义类型转换六…

详解SwinIR的论文和代码(SwinIR: Image Restoration Using Swin Transformer)

paper&#xff1a;https://arxiv.org/abs/2108.10257 code&#xff1a;https://github.com/JingyunLiang/SwinIR 目录 1. Swin Transformer layers1.1 局部注意力1.2 移动窗口机制1.3 关键代码理解 2. 整体网络结构2.1 浅层特征提取2.2 深层特征提取2.3 图像重建 3.总结 SwinI…

BUUCTF 秘密文件 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 深夜里&#xff0c;Hack偷偷的潜入了某公司的内网&#xff0c;趁着深夜偷走了公司的秘密文件&#xff0c;公司的网络管理员通过通过监控工具成功的截取Hack入侵时数据流量&#xff0c;但是却无法分析出Hack到底偷走…

Azure 机器学习 - 搜索中的检索增强 (RAG)

目录 一、Azure AI 信息检索系统介绍二、采用 Azure AI 搜索的 RAG 方法三、适合 Azure AI 搜索的自定义 RAG 模式四、Azure AI 搜索中的可搜索内容五、Azure AI 搜索中的内容检索构建查询响应按相关性排名适用于 RAG 方案的 Azure AI 搜索查询的示例代码 六、集成代码和 LLM七…

【MySQL】_JDBC

目录 1. JDBC原理 2. 导入JDBC驱动包 3. 编写JDBC代码实现Insert 3.1 创建并初始化一个数据源 3.2 和数据库服务器建立连接 3.3 构造SQL语句 3.4 执行SQL语句 3.5 释放必要的资源 4. JDBC代码的优化 4.1 从控制台输入 4.2 避免SQL注入的SQL语句 5. 编写JDBC代码实现…

深入Ansible

1.什么是ansible ansible是新出现的自动化运维工具&#xff0c;基于Python开发&#xff0c;集合了众多运维工具&#xff08;puppet、chef、func、fabric&#xff09;的优点&#xff0c;实现了批量系统配置、批量程序部署、批量运行命令等功能。 ansible是基于 paramiko 开发的…

11月20日星期一今日早报简报微语报早读

11月20日星期一&#xff0c;农历十月初八&#xff0c;早报微语早读。 1、T1以3-0横扫WBG&#xff0c;拿下S13冠军&#xff01;Faker豪取第4冠&#xff1b; 2、天舟七号货运飞船已运抵文昌发射场&#xff0c;将于明年初发射&#xff1b; 3、“中韩之战”球票已经售罄&#xf…

没收到Win11 23H2正式版的推送怎么升级到23H2

没收到Win11 23H2正式版的推送怎么升级到23H2&#xff1f;用户反映自己没有收到Win11 23H2正式版的更新推送&#xff0c;又想升级为23H2版本。接下来小编给大家详细介绍不同的升级方法&#xff0c;帮助更多的用户完成Win11 23H2系统的更新&#xff0c;升级后就能体验到Win11 23…

解锁安全与信任的双重礼遇!JoySSL证书买二送一,买三送二

JoySSL是业内领先的SSL证书提供商&#xff0c;致力于为网站提供最高水平的安全性。通过使用JoySSL证书&#xff0c;您的网站将获得强大的加密保护&#xff0c;确保用户的敏感信息在传输过程中得到安全加密&#xff0c;有效地抵御各种网络威胁。 为何选择JoySSL证书&#xff1f…

解决龙芯loongarch64服务器编译安装Python后yum命令无法使用的问题“no module named ‘dnf‘”

引言 在使用Linux系统时,我们经常会使用yum来管理软件包。然而,有时候我们可能会遇到yum不可用的情况,其中一个原因就是Python的问题。本文将介绍Python对yum可用性的影响,并提供解决方案。 问题引发 正常情况下,安装linux系统后,yum命令是可用状态,升级Python版本后,…
最新文章