C++入门(有C语言基础)

string类

  1. string类初始化的方式大概有以下几种:
    string str1;
    string str2 = "hello str2";
    string str3("hello str3");
    string str4(5, 'B');
    string str5[3] = {"Xiaomi", "BYD", "XPeng"};
    string str6 = str5[2];
    str1 = "nihao str1";
  1. 通过size()length() 函数可以获取字符串的长度:
	// 获取长度,不会包含'\0'
    cout << str1.size() << endl;
    cout << str1.length() << endl;
    cout << str4.size() << endl;
    cout << str5[0].size() << endl;
  1. 两种访问字符的方式:通过 [] 运算符或 at() 方法来访问字符串中的某个字符。at() 具有边界检查,如果访问越界会抛出异常,而 [] 不会做边界检查[]导致的越界会产生未定义行为,越界后会访问到其他地址,系统不会报错;at()只要一越界就要抛出错误,程序终止。一个string占32个字节。
    cout << str2[7] << endl;
    cout << str2.at(7) << endl;
    cout << str5[0][2] << endl;
    cout << str5[0].at(2) << endl;
  1. 拼接字符串:
#include <stdio.h>
#include <iostream>
using namespace std;
int main(int argc, char const *argv[])
{
	string str1 = "成长是永远";
	string str2 = "离别是空悬";
	cout << str1 + str2 << endl;
	return 0;
}
  1. 比较字符串:可以直接使用 ==, !=, <, >, <=, >= 来比较两个字符串的字典顺序。对应ASCII码值大的就大,逻辑表达式为真返回1,为假返回0.
	string str1 = "abc";
    string str2 = "xyz";
    cout << (str1 <= str2) << endl;
  1. 子字符串提取:substr() 函数用于提取子字符串。它接受两个参数:起始索引和长度(可选)
    string str1 = "abcdefghijkl";
    string str2 = str1.substr(1, 10);
    cout << str2 << endl;
  1. 插入删除和替换操作:
string str1 = "hello"; 
str1.insert(5, " world");// 表示在第5个字符后插入字符串

string str1 = "hello world";
str1.erase(5, 3);  // 删除第5个字符之后的3个字符

string str1 = "hello world";
str1.replace(5, 6, "C++"); // 从第5个字符后开始替换,替换6个字符,替换为“C++”
  1. 查找字符串:find() 函数可以查找子字符串或字符的第一个出现位置,如果没有找到,find() 会返回 std::string::npos,这里因为我开头用了using namespace std;,所以不需要再用std::声明
	string str1 = "hello world";
    if (str1.find("world") != string::npos)
    {
        cout << "I find it" << endl;
    }
    else
    {
        cout << "I can't find it" << endl;
    }
  1. C++风格字符串与C风格字符串转换:
	// `std::string` 转换为C风格字符串(`const char*`)
	string str1 = "hello world";
    const char *str2 = str1.c_str();
    cout << str2 << endl;
    
	// C风格字符串转换为 `std::string`
	const char *str1 = "hello world";
    string str2(str1);
    cout << str2 << endl;
  1. 内存管理:string会自动处理内存分配和释放,不需要手动管理内存。string通过深拷贝的方式处理赋值操作,确保每个字符串对象都有自己独立的内存。
  2. 什么是深拷贝?什么是浅拷贝?
    • 深拷贝:深拷贝是在拷贝的时候将内容申请内存,重新拷贝一份,放到内存中,指针指向这个新拷贝的部分,这样就不会出现析构的时候重复释放的问题了。
    • 浅拷贝:浅拷贝就是增加了一个指向相同堆区的指针,这将导致在析构的时候会重复释放。默认的拷贝构造和运算符重载都是浅拷贝。
  3. 什么是析构:析构(Destructor)是一个特殊的成员函数,用于在对象生命周期结束时清理资源并执行必要的清理工作。析构函数的主要目的包括释放对象在其生命周期内分配的动态内存、关闭文件句柄、释放网络连接等。简单理解就是清理资源的成员函数。

函数

  1. 函数可以设置默认参数,如果调用时不传入参数则使用默认参数值:
void nameCountry(string name = "China")
{
    cout << name << endl;
}
  1. 指针传递和引用传递:
    1. 指针传递在C语言和C++中都能使用,指针传递是通过传递变量的地址来间接修改变量的值。
    2. 引用传递,只能在C++中使用。如下第一种函数就是引用传递。即直接操作传入的变量的引用,传递给函数时,函数内部对引用变量的修改会直接反映到原始变量上。
void swap(int &a, int &b)
{
    int temp = a;
    a = b;
    b = temp;
}

void swap(int *a, int *b)
{
    int temp = *a;
    *a = *b;
    *b = temp;
}
  1. 函数的重载:是一种允许在同一个作用域内定义多个具有相同名字但参数列表不同的函数的特性。
    1. 重载规则:
      1. 参数的类型不同
      2. 参数的个数不同
      3. 参数的顺序不同
    2. 不允许重载的情况:
      1. 仅有返回值不同(函数的返回类型不能作为函数重载的依据)
      2. 函数使用默认参数时,可能会导致重载冲突(默认参数的存在导致二义性)
    3. const 修饰符可以参与函数重载。
    4. 数组和指针的重载:数组类型会退化为指针。(在 C语言 中,数组作为函数参数时也会 退化为指针。)
// 原始参照  
int funcPlus(int x, double y)  
{  
    cout << "这是funcPlus1" << endl;  
    return x + (int)y;  
}  
  
// 参数类型不同  
int funcPlus(double x, double y)  
{  
    cout << "这是funcPlus2" << endl;  
    return (int)(x + y);  
}  
  
// 参数个数不同  
int funcPlus(int x)  
{  
    cout << "这是funcPlus3" << endl;  
    return x * x;  
}  
  
// 参数顺序不同  
int funcPlus(double x, int y)  
{  
    cout << "这是funcPlus4" << endl;  
    return (int)(x + y);  
}

// 以下这种重载也是不允许的
int func(int x, int y = 10)  
{  
    cout << "这是funcPlus5" << endl;  
    return x + (int)y;  
}  
  
int func(int x)  
{  
    cout << "这是funcPlus6" << endl;  
    return x;  
}

void func(int &x); // 非 const 引用 
void func(const int &x); // const 引用,允许重载

// 下面这两种不允许重载,因为数组arr[]会退化为指针
void func(int arr[])  
{  
    cout << "arr[]" << endl;  
    cout << arr[0] << endl;  
}  
  
void func(int *arr)  
{  
    cout << "*arr" << endl;  
    cout << arr[0] << endl;  
}

类与多态性

  1. OOP:面向对象编程
  2. 类在声明时是不申请内存的,只有在实例化时才会初始化(分配)内存
  3. C++支持类的多继承;Java不支持类的多继承(但支持接口的多继承)
class Person
{
private:
    int age;

public:
    string name;

    Person(int a, string name);
    ~Person();  // 析构函数
};

// 类内声明,类外定义
Person::Person(int age, string name)
{
    cout << "构造函数执行:" << endl;
    this->age = age;
    this->name = name;
}

Person::~Person()
{
    cout << "析构函数执行:" << endl;
}
  1. 析构函数的作用:主要作用是在对象的生命周期结束时执行清理工作
    1. 释放动态分配的内存:运行过程中通过 newmalloc 等函数动态分配了内存,析构函数负责调用 deletefree 来释放这些内存。
    2. 释放其他系统资源:对象可能持有除内存以外的系统资源,比如文件句柄、网络连接、数据库连接等。
    3. 执行其他清理工作:析构函数可以用于任何需要在对象销毁时执行的操作,比如保存数据、记录日志等。
    4. 析构函数不接受参数,不能重载
    5. 如果创建了多个实例,析构函数就会执行多次。
  2. 类的访问控制:
    1. public:公开的成员可以在类外部访问。
    2. private:私有的成员只能在类内部访问,不能直接在类外部使用,但可以通过类方法间接调用。
    3. protected:受保护的成员可以在类内部和派生类(如子类)中访问。
  3. 类的静态成员:
    1. 静态成员变量:属于类本身,而不是某个对象。它在所有对象中共享
    2. 静态成员函数:只能访问静态成员变量,不依赖于对象。静态成员可以通过类名直接调用,如:Person::getCount()其中Person是类名,getCount()是静态成员函数
  4. 继承:
    1. 继承 允许一个类(派生类)从另一个类(基类)继承属性和行为。
    2. C++支持单继承和多继承。
    3. 派生类可以直接使用基类的公有和受保护成员。
class Animals
{
public:
    void eat()
    {
        cout << "eating" << endl;
    }
};

class Dog : public Animals
{
public:
    void bark()
    {
        cout << "wow wow" << endl;
    }
};
  1. 友元函数:友元函数不是类的成员函数,但可以访问类的私有和受保护成员。它是在类外定义的,但具有特殊权限。
class Person
{
private:
    int age;

public:
    Person(int age)
    {
        this->age = age;
    }
    friend void getAge(Person);
};

void getAge(Person per)
{
    cout << "岁数是:" <<per.age << endl;
}
  1. 多态:
    1. 多态性允许同一个函数或方法在不同的对象上表现出不同的行为。
    2. C++ 中的多态性通过虚函数、继承和指针或引用实现。
    3. 基本概念:
      1. 编译时多态(静态多态):通过函数重载和运算符重载实现,编译时决定。
      2. 运行时多态(动态多态):通过继承和虚函数实现,运行时决定。
  2. 虚函数:
    1. sound() 是基类 Animal 中的虚函数,DogCat 类分别重写了这个函数。
    2. 在运行时,animalPtr 指向不同的派生类对象时,会根据实际对象的类型来调用相应的 sound() 方法,这就是 运行时多态
  3. 纯虚函数与抽象类:
    1. 纯虚函数 是在基类中声明但没有实现的虚函数。
    2. 通过定义纯虚函数,基类变为 抽象类,它不能被实例化,只能作为派生类的基类使用。
  4. 纯虚函数与抽象类的代码如下:
#include <iostream>
using namespace std;

class Animal
{
public:
    virtual void sound() = 0;
};

class Dog : public Animal
{
public:
    // override 关键字不是必须的,但它是一个强烈推荐使用的修饰符。
    void sound() override
    {
        cout << "Dog barks" << endl;
    }
};

class Cat : public Animal
{
public:
    void sound() override
    {
        cout << "Cat meow" << endl;
    }
};

int main(int argc, char const *argv[])
{
    Animal *animalptr;
    Dog dog;
    Cat cat;
    // 基类指针指向派生类对象
    animalptr = &dog;
    animalptr->sound();  // 输出Dog barks
    animalptr = &cat;
    animalptr->sound();  // 输出Cat meow

    return 0;
}
  1. 多态与析构函数:
    1. 通过基类指针删除派生类对象时,如果基类的析构函数不是 virtual,则可能会发生 内存泄漏
    2. 因为如果基类指针的析构函数不是虚函数,那么通过基类指针删除派生类对象时,调用的是基类的析构函数,导致派生类的资源没有被正确释放
  2. 代码如下:
#include <iostream>
using namespace std;

class Base
{
public:
    virtual ~Base()
    { // 虚析构函数
        cout << "基类 析构函数执行" << endl;
    }
};

class Derived : public Base
{
public:
    ~Derived() override
    {
        cout << "派生类 析构函数执行" << endl;
    }
};

int main()
{
    Base *basePtr = new Derived;
    delete basePtr; // 先调用派生类的析构函数,再调用基类的析构函数
    return 0;
}
  1. 对象切片
    1. 如果通过 值传递(而非指针或引用)传递对象,会发生 对象切片,即派生类对象的派生部分会被切掉,变成一个基类对象。
#include <iostream>
using namespace std;

class Base
{
public:
    virtual void show()
    {
        cout << "Base show" << endl;
    }
};

class Derived : public Base
{
public:
    void show() override
    {
        cout << "Derived show" << endl;
    }
};

void display(Base &obj) // 通过引用传递对象不会导致“对象切片”
// void display(Base obj)  // 值传递会导致“对象切片”
{
    obj.show();
}

int main()
{
    Derived d;
    display(d);
    return 0;
}
  1. 对象传递最好是传递指针或者引用,直接进行值传递会导致对象切片:
#include <iostream>

using namespace std;

class Animal
{
public:
    virtual void sound()
    {
        cout << "Animal sound" << endl;
    }
};

class Dog : public Animal
{
public:
    void sound() override
    {
        cout << "Dog barks" << endl;
    }
};

int main(int argc, char const *argv[])
{
    Dog dog;
    dog.sound();  // 输出是Dog barks

    Animal *basePtr = &dog;
    basePtr->sound();  // 输出是Dog barks

    Animal &baseRef = dog;
    baseRef.sound();  // 输出是Dog barks

    Animal baseObj = dog;
    baseObj.sound();  // 输出是Animal sound(这里产生了对象切片)

    return 0;
}

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

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

相关文章

视频集成与融合项目中需要视频编码,但是分辨率不兼容怎么办?

在众多视频整合项目中&#xff0c;一个显著的趋势是融合多元化的视频资源&#xff0c;以实现统一监管与灵活调度。这一需求促使项目团队不断探索新的集成方案&#xff0c;确保不同来源的视频流能够无缝对接&#xff0c;共同服务于统一的调看与管理平台&#xff0c;进而提升整体…

MobaXterm基本使用 -- 服务器状态、批量操作、显示/切换中文字体、修复zsh按键失灵

监控服务器资源 参考网址&#xff1a;https://www.cnblogs.com/144823836yj/p/12126314.html 显示效果 MobaXterm提供有这项功能&#xff0c;在会话窗口底部&#xff0c;显示服务器资源使用情况 如内存、CPU、网速、磁盘使用等&#xff1a; &#xff08;完整窗口&#xff0…

GAMES101(17~18节,物理材质模型)

材质 BRDF 材质&#xff1a;决定了光线与物体不同的作用方式 BRDF定义了物体材质,包含漫反射和镜面部分 BSDF &#xff08;scattering散射&#xff09; BRDF&#xff08;reflect反射&#xff09; BTDF 光线打击到物体上会向四面八方散射 反射 光线打击到物体上反射出去…

MATLAB案例 | Copula的密度函数和分布函数图

本文介绍各种类型&#xff08;Gaussian、t、Gumbel、Clayton、Frank&#xff09;Copula的密度函数和分布函数图的绘制 完整代码 clc close all clear%% ********************计算Copula的密度函数和分布函数图************************ [Udata,Vdata] meshgrid(linspace(0,1…

C#自定义工具类-数组工具类

目录 数组工具类基本操作 1.排序&#xff1a;升序&#xff0c;降序 2.查找 1&#xff09;查找最值&#xff1a;最大值&#xff0c;最小值 2&#xff09;查找满足条件的单个对象 3&#xff09;查找满足条件的所有对象 4&#xff09;选取数组中所有对象的某一字段 完整代…

查缺补漏----程序查询方式和中断方式计算题

1.程序查询方式 总结下来就是&#xff1a; 必须在外设传输完端口大小的数据时访问端口&#xff0c;以防止数据未被及时读出而丢失。 占CPU总时间&#xff1a;就是某段时间内设备用了多少时钟周期/PCU有多少个时钟周期 CPU的时钟周期数&#xff1a;就看主频&#xff0c;主频表示…

大数据开发--1.1大数据概论

目录 一.大数据的概念 什么是大数据&#xff1f; 二. 大数据的特点 三. 大数据应用场景 四. 大数据分析业务步骤 大数据分析的业务流程&#xff1a; 五.大数据职业规划 职业方向 岗位技术要求 六. 大数据学习路线 一.大数据的概念 什么是大数据&#xff1f; 数据 世界…

Spring Boot技术:构建高效网上购物平台

第3章 系统分析 3.1 可行性分析 在系统开发之初要进行系统可行分析&#xff0c;这样做的目的就是使用最小成本解决最大问题&#xff0c;一旦程序开发满足用户需要&#xff0c;带来的好处也是很多的。下面我们将从技术上、操作上、经济上等方面来考虑这个系统到底值不值得开发。…

车辆重识别(注意力 U-Net:学习在哪些区域寻找胰腺)论文阅读2024/10/01

什么是注意力机制&#xff1f; 什么是加性注意力&#xff1f; 大致说一下流程&#xff1a; 对于一张特征图来说&#xff0c;对于这张图中的每一个像素向量&#xff08;例如a&#xff09;&#xff0c;计算该向量与所有像素向量的相似度&#xff0c;对这些相似度进行激活函数…

【重学 MySQL】四十五、数据库的创建、修改与删除

【重学 MySQL】四十五、数据库的创建、修改与删除 一条数据存储的过程数据输入数据验证数据处理数据存储数据持久化反馈与日志注意事项 标识符命名规则基本规则长度限制保留字与特殊字符命名建议示例 MySQL 中的数据类型创建数据库创建数据库时指定字符集和排序规则 查看数据库…

数据库重建索引的作用?

重建索引是数据库管理中的一个重要操作&#xff0c;主要用于优化数据库性能和提高查询效率。以下是重建索引的一些主要用途&#xff1a; 提高查询性能&#xff1a;随着时间的推移&#xff0c;数据的插入、更新和删除会导致索引碎片化&#xff0c;重建索引可以减少碎片&#xf…

DNS with libevent

DNS with libevent: high-level and low-level functionality libevent提供了少量用于解析DNS名字的API&#xff0c;以及用于实现简单DNS服务器的机制。 我们从用于名字查询的高层机制开始介绍&#xff0c;然后介绍底层机制和服务器机制。 Portable blocking name resolution…

15年408计算机网络

第一题&#xff1a; 解析&#xff1a; 接收方使用POP3向邮件服务器读取邮件&#xff0c;使用的TCP连接&#xff0c;TCP向上层提供的是面向连接的&#xff0c;可靠的数据传输服务。 第二题&#xff1a; 解析&#xff1a;物理层-不归零编码和曼彻斯特编码 编码1&#xff1a;电平在…

CSS中字体图标的使用

引言&#xff1a; 在网页设计当中&#xff0c;会有很多很简洁的图标&#xff0c;比如箭头&#xff0c;照相机&#xff0c;放大镜等 这些大概率都是使用字体图标来完成的&#xff0c;因为字体图标比较简洁高效&#xff0c;不会像图片一样需要向浏览器请求数据。那么字体图标该…

网络协议详解--IPv6

IPv6产生背景 &#xff08;1&#xff09;地址空间的耗尽&#xff1a;因特网呈指数级发展&#xff0c;导致IPv4地址空间几乎耗尽。虽然采用了子网划分、CIDR和NAT地址转换技术&#xff0c;但这没有从根源解决地址耗尽的问题 &#xff08;2&#xff09;IP层安全需求的增长&#x…

Oracle exadata存储节点更换内存操作及报错处理

1.报错信息 在进行Oracle exadata巡检时&#xff0c;发现cell节点有一根内存报错&#xff0c;报错信息如下&#xff1a; 报错内存位置为&#xff1a;CPU1 P1/D2槽位 报错内存信息&#xff1a; 根据报错信息确认内存PN号、大小等息&#xff0c;并将信息反馈公司&#xff0c;及…

Hadoop框架及应用场景说明

Hadoop是一个开源的分布式系统基础架构。由多个组件组成&#xff0c;组件之间协同工作&#xff0c;进行大规模数据集的存储和处理。 本文将探讨Hadoop的架构以及应用场景。 一Hadoop框架 Hadoop的核心组件包含&#xff1a; 1. Hadoop分布式文件系统&#xff08;HDFS&#xff…

Qt --- 常用控件的介绍---Widget属性介绍

一、控件概述 编程&#xff0c;讲究的是站在巨人的肩膀上&#xff0c;而不是从头发明轮子。一个图形化界面上的内容&#xff0c;不需要咱们全都从零区实现&#xff0c;Qt中已经提供了很多内置的控件了&#xff08;按钮&#xff0c;文本框&#xff0c;单选按钮&#xff0c;复选…

【Java SE 题库】移除元素(暴力解法)--力扣

&#x1f525;博客主页&#x1f525;&#xff1a;【 坊钰_CSDN博客 】 欢迎各位点赞&#x1f44d;评论✍收藏⭐ 目录 1. 题目 2. 解法(快慢“指针”) 3. 源码 4. 小结 1. 题目 给你一个数组 nums 和一个值 val&#xff0c;你需要原地移除所有数值等于 val 的元素。元素的顺…

C0007.Clion中添加ui文件及运行的完整步骤

1.创建ui文件 选择Ui文件目录&#xff0c;右击&#xff0c;打开Qt Designer&#xff1b; 创建完成后&#xff0c;保存ui界面&#xff0c;并且命名为test.ui&#xff1b; 2.新建头文件test.h 在include目录中&#xff0c;新建头文件&#xff0c;文件名为test.h 3.新建test.…