C++(学习)2024.9.19

news2024/11/10 22:03:02

目录

面向对象基础

类与对象

概念

类的内容

创建对象

封装

构造函数

基本使用

构造初始化列表

隐式调用与显式调用

拷贝构造函数

浅拷贝

 深拷贝

析构函数

作用域限定符:

名字空间

类内声明,类外定义

面向对象基础

类与对象

概念

类:类是一个抽象的概念,用于描述同一类对象的特点。
对象:根据类的概念所创造的实体。

必须要先写类才能创建对象。

类的内容

类中最基础的内容包括两个部分,一个是属性,一个是行为。
属性:表示一些特征项的数值,比如说:身高、体重、肤色、性别、重量、颜色、型号等等。而这些特征项的数值也被称为成员变量。属性一般以名词存在。
行为:表示能执行的动作,能干什么事?比如说:吃饭、睡觉、打架、打篮球。行为一般函数实现,也被称为成员函数。行为一般以动词存在。

成员 = 成员函数+成员变量。

class MobilePhone// 帕斯卡命名法(大驼峰命名法)
{
public: 
    string brand;   // 品牌
    string model;   // 型号
    int weight; // 重量

    void play_music()
    {
        cout << "音乐ing" << endl;
    }

    void run_game()
    {
        cout << "LOL、原神、王者荣耀、开心消消乐、" << endl;
    }

    void call()
    {
        cout << "hello" << endl;
    }
};

创建对象

1.栈内存对象

#include <iostream>
using namespace std;
int main()
{
    MobilePhone mp;
    mp.brand = "xiaomi";
    mp.model = "11 Pro";
    mp.weight = 200;

    cout << mp.brand << " " << mp.model << " " << mp.weight << " " << endl;
    mp.play_music();
    mp.run_game();
    mp.call();

    return 0;
}

2.堆内存对象

        必须使用new关键字创建,使用指针保存。如果不使用delete关键字销毁,则堆内存对象会持续存在。而导致内存泄漏。堆内存对象在调用成员时,使用->而不是"."

#include <iostream>
using namespace std;
int main()
{
    MobilePhone* mp = new MobilePhone;  // 堆内存对象
    mp->brand = "huawei";
    mp->model = "mate 30";
    mp->weight = 200;

    cout << mp->brand << " " << mp->model << " " << mp->weight << endl;

    mp->play_music();
    mp->run_game();
    mp->call();

    delete mp;  // 手动销毁
    mp = NULL; 

    return 0;
}

封装

        类与结构体差别不大,实际上可以认为结构体就是一种完全开放的类。
        封装指的是,将类的一些属性和细节隐藏。重新提供外部访问接口,封装可以提升代码的安全性,并且可以让程序员更关注于上层架构而非内部细节。

#include <iostream>
using namespace std;
class MobilePhone
{
private:    // 私有权限,private是最封闭的权限,只能在类内访问
    string brand;   // 品牌
    string model;   // 型号
    int weight = 200; // 重量

public: // 权限:public最开放的权限
    // geter 读函数
    string get_brand()
    {
        return brand;
    }

    // seter 写函数
    void set_brand(string b)
    {
        brand = b;
    }

    // 读函数
    string get_model()
    {
        return model;
    }

    // seter 写函数
    void set_model(string m)
    {
        model = m;
    }

    // get
    int get_weight()
    {
        return weight;
    }
};

int main()
{
    MobilePhone mp1;    // 栈内存对象
    mp1.set_brand("pingguo");
    mp1.set_model("15 Pro");

    cout << mp1.get_brand() << " " << mp1.get_model() << " " << mp1.get_weight() << endl;

    MobilePhone *mp2 = new MobilePhone; // 堆内存对象
    mp2->set_brand("pingguo");
    mp2->set_model("16 pro");

    cout << mp2->get_brand() << " " << mp2->get_model() << " " << mp2->get_weight() << endl;

    return 0;
}

构造函数

基本使用

构造函数是一种特殊的成员函数,用于创建对象时初始化。创建对象时必须直接或者间接调用当前类的任意一个构造函数。

构造函数写法上有以下要求:

        1.函数名称必须与类名完全相同
        2.构造函数不写返回值
        3.如果程序员不手动编写构造函数,编译器会自动添加一个默认的无参数的构造函数,只要添加任意构造函数后,编译器将不再补充默认无参数的构造函数。

        构造函数在创建对象时,常用于给对象的属性赋予初始值。构造函数也支持函数重载,构造函数也支持函数参数默认值

#include <iostream>
using namespace std;

class MyPhone{
private:

    string pinpai;//品牌
    string xinghao;//型号
    int zhongliang;//重量

public:

    MyPhone()
    {
        cout <<"调用无参构造函数"<<endl;
        pinpai="小米";
        xinghao="11 Pro";
        zhongliang=205;
    }

    MyPhone(string a,string b,int c)
    {
        cout <<"调用有参构造函数"<<endl;
        pinpai=a;
        xinghao=b;
        zhongliang=c;
    }

    string getPinpai()
    {
        return pinpai;
    }

    void setPinpai(string value)
    {
        pinpai = value;
    }

    string getXinghao()
    {
        return xinghao;
    }

    void setXinghao(string value)
    {
        xinghao = value;
    }

    int getZhongliang()
    {
        return zhongliang;
    }
};

int main()
{
    MyPhone *mp=new MyPhone("苹果","16 Pro",200);
    cout <<"手机为"<<mp->getPinpai()<<" "<<mp->getXinghao()<<" 重量为:"<<mp->getZhongliang()<<"g"<<endl;
    delete mp;
    mp=NULL;

    MyPhone a;
    cout <<"手机为"<<a.getPinpai()<<" "<<a.getXinghao()<<" 重量为:"<<a.getZhongliang()<<"g"<<endl;

    return 0;
}

构造初始化列表

构造初始化列表是一种更简单的给成员变量赋予初始值的写法。

#include <iostream>
using namespace std;
class MobilePhone
{
private:   
    string brand;  
    string model;   
    int weight;
public: 
    MobilePhone():brand("8848"),model("M6巅峰版"),weight(300){}
    MobilePhone(string b,string m,int w):brand(b),model(m),weight(w){}
    string get_brand()
    {
        return brand;
    }
    string get_model()
    {
        return model;
    }
    int get_weight()
    {
        return weight;
    }
};

int main()
{
    MobilePhone mp1("小米","su7",300); 
    cout << mp1.get_brand() << " " << mp1.get_model() << " " << mp1.get_weight() << endl;
    return 0;
}

当构造函数的局部变量与成员变量重名时,除了使用后面学习的this指针的方式外,还可以使用构造初始化列表区分。

隐式调用与显式调用

构造函数的调用可以分为显式调用与隐式调用。
        显式调用是指在创建对象时手写构造函数的名称,与参数列表。
        隐式调用指的是在创建对象的时候不写构造函数的参数列表,编译器会尝试调用对应参数的构造函数。

#include <iostream>
using namespace std;
class Student
{
private:
    int age;
public:
    explicit Student(int a):age(a)
    {
        cout << "构造函数" << endl;
    }
    Student():age(1)
    {
        cout << "无参构造函数" << endl;
    }
    int get_age()
    {
        return age;
    }
};
int main()
{
    Student s1(12); // 显式调用
    cout << s1.get_age() << endl;
    Student s3 = Student(14);   // 显式调用
    cout << s3.get_age() << endl;
    // Student s4 = 15;    // 隐式调用
    // cout << s4.get_age() << endl;
    Student* s2 = new Student(13);  // 显式调用
    cout << s2->get_age() << endl;
    Student s5;
    cout << s5.get_age() << endl;
    return 0;
}

建议使用显式调用,可以使用explict关键字屏蔽隐式调用语法。

拷贝构造函数

        当程序员不手写拷贝构造函数时,编译器会自动添加一个拷贝构造函数,使对象创建可以通过这个构造函数实现。

#include <iostream>
using namespace std;
class Student
{
private:
    int age;
public:
    Student(int a):age(a)
    {
        cout << "构造函数" << endl;
    } 
    Student(const Student &st)
    {
        age = st.age;
        cout << "拷贝构造函数被调用了" << endl;
    }
    int get_age()
    {
        return age;
    }
};
int main()
{
    Student s1(12);
    cout << s1.get_age() << endl;
    Student s2(s1);     // 拷贝构造函数
    cout << s2.get_age() << endl;
    return 0;
}

拷贝构造函数存在隐患,当成员变量出现指针类型时,默认的拷贝构造函数会导致两个对象的成员变量指向同一处,不合符面向对象的设计规范,这种现象被称为“浅拷贝”。

浅拷贝
#include <iostream>
#include <string.h>
using namespace std;
class Dog
{
private:
    char *name;
public:
    Dog(char *n)
    {
        name = n;
    }
    void show_name()
    {
        cout << name << endl;
    }
};
int main()
{
    char arr[20] = "旺财";
    Dog d1(arr);
    Dog d2(d1); // 拷贝构造函数
    strcpy(arr,"大黄");   // 更改外部内存,对象内部的数据也跟着进行更改,因为操作的同一块内存空间
    d1.show_name(); // 大黄
    d2.show_name(); // 大黄
    return 0;
}

这种情况必须手动重写构造函数,使每次赋值都创建一个新的副本,从而每个对象单独持有自己的成员变量,这种方式被称为“深拷贝”。

 深拷贝
#include <iostream>
#include <string.h>
using namespace std;
class Dog
{
private:
    char *name;
public:
    Dog(char *n)
    {
        name = new char[20];
        strcpy(name,n);
    }
    Dog(Dog &d)
    {
        name = new char[20];
        strcpy(name,d.name);
    }
    void show_name()
    {
        cout << name << endl;
    }
};
int main()
{
    char arr[20] = "旺财";
    Dog d1(arr);
    Dog d2(d1); // 拷贝构造函数
    strcpy(arr,"大黄");
    d1.show_name(); // 旺财
    d2.show_name(); // 旺财
    return 0;
}

在需求不受影响的情况下,可以通过屏蔽拷贝构造函数(私有化),来解决浅拷贝的问题。深拷贝的代码也存在隐患,new开辟的空间无法方便的进行释放,造成内存泄漏的问题。

补充:
1、添加无参构造函数,编译器还会添加默认无参构造函数嘛?(不会)
2、添加任意构造函数,编译器还会添加默认无参构造函数嘛?(不会)
3、添加无参构造函数,编译器还会添加默认拷贝构造函数嘛?(会)
4、添加拷贝构造函数,编译器还会添加默认拷贝构造函数嘛?(不会)

析构函数

析构函数是与构造函数对立的函数。

构造函数析构函数
创建对象时手动调用当对象销毁时,自动调用
函数名称是类名 函数名称是~类名
构造函数可以重载析构函数没有参数,不能重载
用于创建对象时并初始化用于销毁对象时释放资源
有返回值但是不写,返回值是新创建的对象  没有返回值
#include <iostream>
#include <string.h>
using namespace std;
class Dog
{
private:
    char *name;
public:
    Dog(char *n)
    {
        name = new char[20];
        strcpy(name,n);
    }
    Dog(Dog &d)
    {
        name = new char[20];
        strcpy(name,d.name);
    }
    void show_name()
    {
        cout << name << endl;
    }
    ~Dog()
    {
        cout << "析构函数被调用了" << endl;
        delete []name;
    }
};
int main()
{
    char arr[20] = "旺财";
    Dog d1(arr);
    Dog d2(d1); // 拷贝构造函数
    strcpy(arr,"大黄");
    d1.show_name(); // 旺财
    d2.show_name(); // 旺财
    Dog *d3 = new Dog(arr);
    delete d3;  // 销毁时调用析构函数
    return 0;
}

作用域限定符:

名字空间

#include <iostream>
#include <string.h>
using namespace std;
namespace my_space// 名字空间
{
    int a = 3;
    int b = 4;
}
using namespace my_space;
int a = 2;
int main()
{
int a = 1;
cout << a << endl; // 就近原则,打印1
cout << ::a << endl; // ::全局作用域(匿名名字空间)2
cout << my_space::a << endl; // 3
cout << b << endl; // 4
return 0;
}

类内声明,类外定义

#include <iostream>
using namespace std;
class Demo
{
public:
    // 类内声明
    Demo();
    void test(string str);
};
// 类外定义
Demo::Demo()
{
    cout << "创建了一个对象" << endl;
}
void Demo::test(string str)
{
    cout << "string:" << str << endl;
}
int main()
{
    Demo d1;
    d1.test("hello");
    return 0;
}


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

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

相关文章

Jboss Administration Console弱⼝令

漏洞描述 Administration Console管理⻚⾯存在弱⼝令&#xff0c;admin:admin&#xff0c;登陆后台上传war包 , getshell 影响版本 全版本 环境搭建 因为这⾥⽤的环境是CVE-2017-12149的靶机 cd vulhub-master/jboss/CVE-2017-12149 docker-compose up -d 密码⽂件 /j…

【SA8155P】AIS Camera相关内容的简单介绍

高通车载相机模块(AIS,Automotive lmage System)是专门针对车载系统特性而设计的一套车载视觉架构,可用于AVM、RVC、DMS等常见车载视频应用开发。车载Camera系统的图像大部分是给自动驾驶等使用,更多考虑的是远距离传输、多摄像头图像处理等场景。 本文仅对AIS Camera相关…

MySQL的登陆错误:ERROR 1049 (42000): Unknown database ‘root‘

MySQL的登陆错误&#xff1a;ERROR 1049 (42000): Unknown database ‘root’ 安装MySQL的时候&#xff0c;到网上查的命令行登陆MySQL的方法都是mysql -u root -p password mysql -r root -p 123456但是奇怪的是这条命令我输进去死活都不对&#xff0c;它都会要求再输入一遍…

21、Tomato

难度 低(个人认为中) 目标 root权限 一个flag 使用VMware启动 kali 192.168.152.56 靶机 192.168.152.66 信息收集 端口信息收集 可以看到有个ftp服务&#xff0c;2211实际是ssh协议端口&#xff0c;80、8888是一个web服务 web测试 80端口显示一个tomato 查看源码给了一些…

从0开始学ARM

1. ARM模式和寄存器 1.1 ARM处理器工作模式 Cortex系列之前的ARM处理器工作模式一共有7种。 1.1.1 工作模式 Cortex系列的ARM处理器工作模式有8种&#xff0c;多了1个monitor模式&#xff0c;如下图所示&#xff1a; ARM之所以设计出这么多种模式出来&#xff0c;就是为了…

三菱变频器RS-485 端子的接线和构成

RS-485 端子排列 RS-485 端子接线方法 RS-485 的计算机1台、变频器1台时 RS-485 的计算机1台、变频器n台(多台)时 通讯运行的初始设定 1、为使变频器和计算机进行 RS-485 通讯&#xff0c;进行必要的设定。 2、通讯分为使用变频器的PU接口的通讯和使用RS-485端子的通讯。 3、…

搜索引擎onesearch3实现解释和升级到Elasticsearch v8系列(四)-搜索

搜索 搜索内容比较多&#xff0c;onesearch分成两部分&#xff0c;第一部分&#xff0c;Query构建&#xff0c;其中包括搜索词设置&#xff0c;设置返回字段&#xff0c;filter&#xff0c;高亮&#xff1b;第二部分分页和排序。第一部分是映射引擎负责&#xff0c;映射通用表…

SAP B1 流程实操 - 营销单据销售部分(下)

背景 在 SAP B1 中&#xff0c;最重要的模块就是【销售】&#xff0c;企业可能不涉及生产和库存&#xff08;贸易公司&#xff09;&#xff0c;甚至不涉及采购&#xff08;服务业&#xff09;&#xff0c;但是一定会有基本的 销售。本文中我们讲解 销售 模块的基本核心&#x…

2024年最新苹果cms升级插件【泛目录专用】

苹果CMS是一款专为视频内容管理而设计的系统&#xff0c;近年来在视频站点搭建中逐渐成为热门选择。其直观的用户界面和灵活的管理功能&#xff0c;使得无论是新手还是专业开发者都能轻松上手。 苹果CMS提供了多种主题和模板&#xff0c;用户可以根据自身需求进行定制&#xf…

Python画笔案例-054 绘制流光溢彩动画

1、绘制流光溢彩动画 通过 python 的turtle 库绘制 流光溢彩动画&#xff0c;如下图&#xff1a; 2、实现代码 绘制流光溢彩动画&#xff0c;以下为实现代码&#xff1a; """本程序实现流光溢彩的动画效果 """ from turtle import * from color…

from tqdm.auto import tqdm用法详细介绍

tqdm 是一个 Python 库&#xff0c;用于在长时间运行的任务中显示进度条。tqdm.auto 是 tqdm 的一个版本&#xff0c;能够自动适配输出环境&#xff08;如 Jupyter Notebook、命令行等&#xff09;&#xff0c;以确保进度条在各种环境下显示正确。下面是 tqdm.auto 的详细用法介…

【刷题】杨辉三角

目录 杨辉三角题目描述解题思路解题代码 相同的树题目描述解题思路 二叉树的层序遍历题目描述解题思路解题代码从底层层序遍历 二叉树的最近公共祖先题目描述解题思路 从前序与中序遍历序列构建二叉树题目描述解题思路 从后序与中序遍历序列构建二叉树题目描述解题思路 根据二叉…

SAP-MM-变式的设置

1、报表变式 业务需求: 业务人员查询报表时有些值是需要经常输入的,能不能设置成默认值?能不能设置成每次进入报表不选择变式直接是默认值? 解决措施: 1、事物码:MB51 以MB51物料凭证查询为例,其他报表自行举一反三 2、设置变式 首先进入MB51入下图 上图是没有选…

任天堂发言人:不会透露起诉《幻兽帕鲁》开发商细节

任天堂在昨天突然宣布将起诉《幻兽帕鲁》开发商 Pocketpair&#xff0c;除了引起许多玩家不满外&#xff0c;更多的是所有人的疑惑&#xff1a;因为实际上大家内心里觉得任天堂出手是理所当然的&#xff0c;但是为什么是在游戏发布数月后才选择起诉&#xff1f;此次诉讼是“专利…

吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)2.1-2.2

目录 第四门课 卷积神经网络&#xff08;Convolutional Neural Networks&#xff09;第二周 深度卷积网络&#xff1a;实例探究&#xff08;Deep convolutional models: case studies&#xff09;2.1 为什么要进行实例探究&#xff1f;&#xff08;Why look at case studies?&…

Python编码系列—Python外观模式:简化复杂系统的快捷方式

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

生信初学者教程(八):数据收集

文章目录 数据分布表达谱数据最终数据分布自动下载GSE14520下载GSE149614下载其它数据在确定研究疾病为肝细胞癌**(Liver Hepatocellular Carcinoma: HCC)**后,系统地进行了文献回顾,专注于搜索与HCC相关的荟萃分析文章,以获取该领域的研究动态和已有成果。为了支持的研究…

卡车配置一键启动无钥匙进入手机控车

‌ 卡车智能一键启动无钥匙进入手机控车&#xff0c;通过手机应用程序与汽车内置硬件、软件的无线通信&#xff0c;实现对汽车的远程控制‌。 卡车改装一键启动的步骤包括安装门把手的感应装置、拆卸仪表台和门板&#xff0c;取出内部的待接线束&#xff0c;并将一键启动…

MySQL高阶1875-将工资相同的雇员分组

目录 题目 准备数据 分析数据 题目 编写一个解决方案来获取每一个被分配到组中的雇员的 team_id 。 返回的结果表按照 team_id 升序排列。如果相同&#xff0c;则按照 employee_id 升序排列。 这家公司想要将 工资相同 的雇员划分到同一个组中。每个组需要满足如下要求&a…

springboot结合p6spy进行SQL监控

1.学习p6spy的相关链接 英文文档&#xff1a;Integrating P6Spy — p6spy 3.9.2-SNAPSHOT documentationhttps://p6spy.readthedocs.io/en/latest/integration.html github链接&#xff1a;GitHub - p6spy/p6spy: P6Spy is a framework that enables database data to be sea…