C++(学习)2024.9.20

news2024/9/20 23:39:29

目录

C++面向对象的基础知识

this指针

概念

功能

1.类内调用成员

2.区分重名的成员变量和局部变量

3. 链式调用

static关键字

1.静态局部变量

2.静态成员变量

3.静态成员函数

4.单例设计模式

const关键字

1.const修饰成员函数

2.const修饰对象

3.const修饰成员变量

4.const修饰局部变量

运算符重载

友元

1.概念

2.友元函数

3.友元类

4.友元成员函数


C++面向对象的基础知识

this指针

概念

this指针是一个特殊的指针,指向当前类对象的首地址。

成员函数(包括构造函数和析构函数)中都有this指针,因此this指针只能在类内使用。实际上this指针指向的就是当前运行的成员函数所绑定的对象。

#include <iostream>
using namespace std;
class Test
{
public:
    void test_this()
    {
        cout << this << endl;
    }
};
int main()
{
    Test t1;
    cout << &t1 << endl;
    t1.test_this();
    Test t2;
    cout << &t2 << endl;
    t2.test_this();
    Test *t3 = new Test;
    cout << t3 << endl;
    t3->test_this();
    delete t3;
    return 0;
}

功能

1.类内调用成员

成员(成员变量+成员函数)必须由对象调用。类中成员的调用都依赖于this指针的,通常由编译器自动添加。

#include <iostream>
using namespace std;
class Test
{
private:
    string name;
public:
    Test(string n)
    {
        this->name = n;
    }
    string get_name()
    {
        return this->name;
    }
};
int main()
{
    Test t1("zhangsan");
    cout << t1.get_name() << endl;
    return 0;
}
2.区分重名的成员变量和局部变量
#include <iostream>
using namespace std;
class Test
{
private:
    string name;
public:
    Test(string name)
    {
        this->name = name;  // 通过this指针在函数体中进行区分
    }
    string get_name()
    {
        return name;
    }
};
int main()
{
    Test t1("zhangsan");
    cout << t1.get_name() << endl;
    return 0;
}
3. 链式调用

支持链式调用的成员函数特点:
●当一个成员函数的返回值是当前类型的引用时,往往表示这个函数支持链式调用。
●return后面是*this。

#include <iostream>
using namespace std;
class Test
{
private:
    int val = 0;
public:
    Test &add(int i)
    {
        val += i;
        return *this;
    }
    int get_val()
    {
        return val;
    }
};
int main()
{
    Test t1;
    t1.add(1);
    t1.add(2);
    t1.add(100);
    cout << t1.get_val() << endl;   // 103
    // 链式调用
    Test t2;
    cout << t2.add(2).add(3).add(200).get_val() << endl;
    return 0;
}

static关键字

1.静态局部变量

使用static修饰局部变量,这样的变量就是静态局部变量。
静态局部变量在第一次调用时创建,直到程序结束后销毁,同一个类的所有对象共用这一份静态局部变量。

#include <iostream>
using namespace std;
class Test
{
public:
    void func()
    {
        int a = 1;
        static int b = 1;
        cout << "a=" << ++a << " " << &a << endl;
        cout << "b=" << ++b << " " << &b << endl;
    }
};
int main()
{
    Test t1;
    t1.func();
    t1.func();
    t1.func();
    Test t2;
    t2.func();
    Test *t3 = new Test;
    t3->func();
    return 0;
}

注意:a可能会在同一个内存地址反复创建销毁。

2.静态成员变量

        使用static修饰成员变量,这样的变量就是静态成员变量。

        需要在类内声明,类外初始化。
        一个类的所有对象共用一份静态成员变量。虽然静态成员变量可以使用对象调用的,但是更建议直接使用类名调用。所以静态成员变量可以脱离对象使用,在程序开始运行时就开辟内存空间,程序执行结束后销毁。
        更推荐使用类名直接调用,代码的可读性更高。

#include <iostream>
using namespace std;
class Test
{
public:
    int a = 1;
    static int b;
};
// 静态成员变量,类外初始化
int Test::b = 1;

int main()
{
    cout << Test::b << &Test::b << endl;

    Test t1;
    cout << t1.a++ << &t1.a << endl;
    cout << t1.b++ << &t1.b << endl;
    cout << " --------------- " << endl;
    Test t2;
    cout << t2.a++ << &t2.a << endl;
    cout << t2.b++ << &t2.b << endl; 

    return 0;
}

3.静态成员函数

使用static修饰成员函数,这样的函数就是静态成员函数。
与静态成员变量相似的有:    
        都可以通过类名直接调用,也可以通过对象进行调用,也可以脱离对象使用。
        静态成员函数没有this指针,不能再静态成员函数中调用同类中其他非静态成员,但是静态成员函数可以调用静态成员。

#include <iostream>
using namespace std;
class Test
{
public:
    void func0()
    {
        //func1();    // 非静态成员函数可以调用静态成员函数
        cout << "非静态成员函数" << endl;
    }

    static void func1(Test &t)
    {
        Test t2;
        t2.func0();
        t.func0();
        //func0();     // 错误 静态成员函数,不能调用非静态成员函数
        cout << "静态成员函数1" << endl;
    }
};

int main()
{
    Test t1;
    Test t;
    t1.func1(t);
    return 0;
}

        静态成员函数内调用当前类的非静态成员需要通过参数将对象传递进来,也可以在函数内创建对象进行调用。

4.单例设计模式

        设计模式是一套被反复使用、多人知晓、经过分类的、代码设计经验的总结。通常用于一些面向对象的语言,如:JAVA、C++、C#等。这里以一个简化版本的单例设计模式为例,讲解static的实际使用。

#include <iostream>
using namespace std;
class Singleton
{
private:
    Singleton(){}
    Singleton(const Singleton&);
    static Singleton *instance; // 静态成员变量
public:
    static Singleton* get_instance()    // 静态成员函数
    {
        if(instance == NULL)
        {
            instance = new Singleton;
        }
        return instance;
    }
    static void delete_instance()
    {
        if(instance != NULL)
        {
            delete instance;
            instance = NULL;
        }
    }
};
Singleton *Singleton::instance = NULL;
int main()
{
    Singleton *s1 =  Singleton::get_instance();
    Singleton *s2 =  Singleton::get_instance();
    cout << s1 << endl;
    cout << s2 << endl;
    return 0;
}

const关键字

1.const修饰成员函数

const修饰的成员函数,表示常成员函数。
特性:
(1)可以调用成员变量,但是不能修改成员变量的值
(2)不能调用非const的修饰的成员函数,哪怕这个函数并没有修改成员变量。

建议只要成员函数不修改成员变量就使用const修饰,例如show、get等等。

#include <iostream>
using namespace std;
class Demo
{
private:
    int a;
public:
    Demo(int a)
    {
        this->a = a;
    }
    void func0()
    {
        cout << "hello" << endl;
    }
    int get_demo()const
    {
        return a;
    }
    
    void test()const    // 常成员函数
    {
        //a++;    // 错误 const修饰的成员函数,不能修改成员变量
        cout << a << endl;
        //func0();    // 错误,const修饰的成员函数,不能调用非const修饰的成员函数
        get_demo();
    }
};
int main()
{
    Demo demo(1);
    demo.test();
    cout << demo.get_demo() << endl;
    return 0;
}

2.const修饰对象

const修饰的对象被称为常量对象,这种对象的成员变量值无法被修改,也无法调用非const的成员函数。

#include <iostream>
using namespace std;
class Demo
{
private:
    int a;
public:
    int b = 20;
    Demo(int a)
    {
        this->a = a;
    }
    void func0()
    {
        cout << "hello" << endl;
    }
    int get_demo()const
    {
        return a;
    }
    void test()const     // 常成员函数
    {
        //a++;     // 错误 const修饰的成员函数,不能修改成员变量
        cout << a << endl;
        //func0();     // 错误,const修饰的成员函数,不能调用非const修饰的成员函数
        get_demo();
    }

};

int main()
{
    const Demo demo(1);    //Demo const demo(1);
    cout << demo.get_demo() << endl; 
    //demo.func0();       // 错误,const修饰对象,无法调用非const修饰的成员函数
    demo.test();
    cout << demo.b << endl;
    //demo.b = 10;     // 错误,const修饰的对象,无法修改成员变量
    return 0;
}

3.const修饰成员变量

const修饰的成员变量为常成员变量,表示该成员变量的值无法被修改。
常成员变量有两种初始化方式:
(1)声明后直接赋值
(2)构造初始化列表

上述两种方式同时使用时,以构造初始化列表为准。

#include <iostream>
using namespace std;
class Demo
{
private:
    const int a = 1;
    const int b = 2;
    const int c = 3;
public:
    Demo(int a,int b,int c):a(a),b(b),c(c){}
    void show()
    {
        cout << a << " " << b << " " << c << endl;
    }
};

int main()
{
    Demo d1(10,20,30);
    d1.show();
    return 0;
}

4.const修饰局部变量

const修饰局部变量,表示该局部变量不可被修改。 这种方式常用于引用参数。

#include <iostream>
using namespace std;

class Demo
{
private:
    const int a = 1;
    const int b = 2;
    const int c = 3;
public:
    Demo(int a,int b,int c):a(a),b(b),c(c){}
    void show()
    {
        cout << a << " " << b << " " << c << endl;
    }
    void test(const int &a1)
    {
        a1++;
        const int d = 10;
    }
};

int main()
{
    int a = 1;
    Demo d1(10,20,30);
    d1.show();
    d1.test(a);
    return 0;
}



运算符重载

友元

1.概念

        类实现了数据的隐藏和封装,类的数据成员一般定义为私有成员,仅能通过类的成员函数才能读写。如果数据成员定义为公共的,则又破坏了封装性。但是再某些情况下,需要频繁的读写类的数据成员,特别是在对某些成员函数多次调用时,由于参数传递,类型检查和安全性检查都需要时间的开销,而影响程序的运行效率。

友元有三种实现方式:

        1.友元函数
        2.友元类
        3.友元成员函数

        友元在于提高程序的运行效率,但是,它破坏了类的封装性和隐藏性,是的非成员函数能够访问类的私有成员,导致程序维护性变差,因此使用友元要慎重。

2.友元函数

        友元函数不属于任何一个类,是一个类外的函数,但是需要在类内进行“声明”。虽然友元函数不是类中的函数,但是却可以访问类中的所有成员(包括私有成员)

#include <iostream>
using namespace std;
class Test
{
private:
    int a;
public:
    Test(int i):a(i){}
    void show()
    {
        cout << a << " " << &a << endl;
    }
    // 友元函数,类内声明
    friend void and_test(Test &t);
};

// 友元函数
void and_test(Test &t)
{
    cout << ++t.a << " " << &t.a << endl;
}

int main()
{
    Test t1(1);
    and_test(t1);
    t1.show();
    return 0;
}

友元函数的使用注意以下几点:
1.友元函数没有this指针
2.友元函数的“声明”可以放置到类中的任何位置,不受权限修饰符的影响。
3.一个友元函数理论上可以访问多个类,只需要再各个类中分别“声明”。

3.友元类

        当一个类成为了另一个类Test的朋友时,类Test的所有成员都可以被类B访问,此时类B就是类Test的友元类。

#include <iostream>
using namespace std;
class Test
{
private:
    int a;
public:
    Test(int i):a(i){}
    void show()
    {
        cout << a << " " << &a << endl;
    }
    // 友元类,类内声明
    friend class B;
};
class B
{
public:
    void and_test(Test &t)
    {
        ++t.a;
        cout << t.a << " " << &t.a << endl;
    }
    void and_test1(Test &t)
    {
        cout << ++t.a << " " << &t.a << endl;
    }
};
int main()
{
    Test t1(1);
    B b;
    b.and_test(t1);
    b.and_test1(t1);
    t1.show();
    return 0;
}

友元类的使用需要注意以下几点:
1.友元关系不能被继承
2.友元关系不具有交换性(比如:类B声明为类Test的友元,类B可以访问类Test中的成员,但是类Test不能访问类B中的私有成员,如果需要访问,需要将类Test声明成类B的友元)
互为友元代码,需要类内声明,类外实现。

#include <iostream>
using namespace std;
class Cat;
class Test
{
private:
    int a;
public:
    Test(int i):a(i){}
    void test(Cat &c);
    friend class Cat;
};
class Cat
{
private:
    int b;
public:
    Cat(int i):b(i){}
    void test1(Test &t);
    friend class Test;
};
void Test::test(Cat &c)
{
    cout <<c.b<<endl;
}
void Cat::test1(Test &t)
{
    cout <<t.a++<<endl;
}
int main()
{
    Test t(44);
    Cat c(12);
    c.test1(t);
    return 0;
}

4.友元成员函数

        使类B中的成员函数成为类Test的友元成员函数,这样类B的该成员函数就可以访问类Test的所有成员了。

#include <iostream>
using namespace std;

// 第四步:声明被访问的类
class Test;
class B
{
public:
    // 第二步:声明友元成员函数(类内声明,类外实现)
    void and_test(Test &t);
};

class Test
{
private:
    int a;
public:
    Test(int i):a(i)
    {
    }

    void show()
    {
        cout << a << " " << &a << endl;
    }

    // 友元成员函数,第一步:确定友元成员函数的格式并声明
    friend void B::and_test(Test &t);
};

// 第三步:类外定义友元成员函数
void B::and_test(Test &t)
{
    ++t.a;
    cout << t.a << " " << &t.a << endl;
}

int main()
{
    Test t1(1);
    B b;
    b.and_test(t1);
    t1.show();
    return 0;
}

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

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

相关文章

算法学习1

知识点 一.时间复杂度二.排序1.选择排序2.冒泡排序 三.异或交换 一.时间复杂度 列如&#xff1a; //长度为n的整型数组 int arr[n];//循环1 for(int i 0 ;i < n; i) {for(int j i;j < n;j){cout << arr[i] << endl;cout << arr[j] << endl;}…

(c语言+数据结构链表)项目:贪吃蛇

目录 1.项目背景 2.游戏效果演⽰ 3. ⽬标 4. 技术要点 5. Win32 API介绍 5.1 Win32 API 5.2 控制台程序 5.3 控制台屏幕上的坐标COORD 5.4 GetStdHandle 5.5 GetConsoleCursorInfo 5.5.1 CONSOLE_CURSOR_INFO 5.6 SetConsoleCursorInfo 5.7 SetConsoleCursorPositi…

统计项目代码行数工具—cloc

目录 引言一、cloc简介二、cloc安装三、cloc使用四、参考博客 引言 项目开发完成&#xff0c;想要查看自己项目的代码行数&#xff0c;强烈推荐一款非常好用的命令行工具-cloc。 一、cloc简介 只需要通过命令行的方式运行cloc&#xff0c;就可以得知指定文件代码行数、注释函…

java--章面向对象编程(高级部分)

类变量和类方法 类变量 类变量内存布局 什么是类变量 类变量也叫 静态变量/静态属性&#xff0c;是该类的所有对象共享的变量&#xff0c;任何一个该类的对象去访问它时&#xff0c;取到的都是相同的值&#xff0c;同样任何一个该类的对象去修改它时&#xff0c;修改的也是同…

基于flask+vue框架的传染病防控酒店信息系统zvt93(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。

系统程序文件列表 项目功能&#xff1a;患者,服务人员,病房类型,病房信息,病房分配,需求箱,商品分类,商品信息,购买商品,分配反馈,健康上报,患者信息,患者分配 开题报告内容 基于flaskvue框架的传染病防控酒店信息系统开题报告 一、项目背景 在全球公共卫生事件频发的背景下…

排序-----选择排序

首先介绍几种排序的分类&#xff1a; 选择排序是每次都遍历&#xff0c;标记出最小的元素&#xff0c;然后把它放在前面。 本文介绍优化后的版本&#xff1a;每次遍历标记出最小的和最大的元素&#xff0c;分别放到前面和后面。&#xff08;注意这里是找到对应的下标&#xff0…

【Python报错已解决】To update, run: python.exe -m pip install --upgrade pip

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 专栏介绍 在软件开发和日常使用中&#xff0c;BUG是不可避免的。本专栏致力于为广大开发者和技术爱好者提供一个关于BUG解决的经…

如何使用ssm实现基于Javaweb的网上花店系统的设计与实现

TOC ssm653基于Javaweb的网上花店系统的设计与实现jsp 研究背景 自计算机发展以来给人们的生活带来了改变。第一代计算机为1946年美国设计&#xff0c;最开始用于复杂的科学计算&#xff0c;占地面积、开机时间要求都非常高&#xff0c;经过数十几的改变计算机技术才发展到今…

docker部署个人网页导航

1&#xff09;效果展示 2&#xff09;步骤 2.1&#xff09;往期部署docker自行查找 2.2&#xff09;CV命令 mkdir ~/onenav&&cd ~/onenav vi docker-compose.yml粘贴内容 version: 3 services:onenav:container_name: onenav #容器名称ports:- "3080:80"…

oracle avg、count、max、min、sum、having、any、all

组函数 having的使用 any的使用 all的使用

交换机VLAN配置

搭建拓扑图 思路&#xff1a; 先配置Access接口属性&#xff0c;包括SW1的e0/0/2&#xff0c;SW2的e0/0/3。配置Trunk端口属性&#xff0c;包括SW1的e0/0/1&#xff0c;SW2的e0/0/1&#xff0c;SW3的e0/0/2、e0/0/3。由于实验要求&#xff0c;同VLAN能够互通---->则允许SW1…

redis分布式锁(看门枸机制)

分布式锁确保在同一时间只有一个节点能获得对共享资源的独占访问权限&#xff0c;从而解决并发访问问题。 Redisson锁(简称看门狗) 它可以实现锁的延长&#xff0c;确保某个线程执行完才能让其他线程进行抢锁操作 引入看门狗机制后 如何使用&#xff1f; 1、引入依赖包 <…

大厂程序员的健身之路

大厂程序员的健身之路 基本信息饮食正餐营养补剂 睡眠训练计划 基本信息 健身时间&#xff1a;2023.03 -> 2024.09体重变化&#xff1a;52kg -> 67kg 饮食 正餐 早餐&#xff1a;不吃午餐&#xff1a;两碗米饭 鱼/鸡肉 蔬菜 酸奶晚餐&#xff1a;两碗米饭 鱼/鸡肉…

《史上最简单的 SpringCloud 教程》

Finchley版本 Spring Cloud Finchley; Spring Boot 2.0.3 史上最简单的 SpringCloud 教程 | 第一篇: 服务的注册与发现&#xff08;Eureka&#xff09;(Finchley版本)史上最简单的SpringCloud教程 | 第二篇: 服务消费者&#xff08;restribbon&#xff09;(Finchley版本)史上最…

栈的各种接口的实现(C)

栈的概念 栈&#xff1a; 一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则。压栈&#xff1a;…

xtop:multi_driven_net与incomplete_timing_cell fail reason 分析

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 xtop做时序收敛时报告fail reason&#x

Cortex_M0开发学习_1

一、简介 意法半导体基于Arm Cortex-M0的STM32F0系列器件实现了32位性能&#xff0c;同时传承了STM32系列的重要特性&#xff0c;特别适合成本敏感型应用。STM32F0 MCU集实时性能、低功耗运算和STM32平台的先进架构及外设于一身。 STM32F0系列产品基于Cortex-M0内核&#xff0c…

基于SpringBoot的中小医院管理系统

系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…

MACCMS 远程命令执行漏洞复现(CVE-2017-17733)

目录 漏洞介绍 工具使用 环境搭建&复现过程 这是我复现的第一个漏洞&#xff08;老天奶&#xff09;&#xff0c;有必要做一个详细的writeup。 漏洞介绍 MACCMS是一套采用PHP/MySQL数据库运行的全新且完善的强大视频电影系统。完美支持众多视频网站和高清播放器(youku,…

Vue3实战:使用 errorHandler 捕获全局错误

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 在 Vue3 中&#xff0c;app.config.errorHandler 是一个错误处理器&#xff0c;用于为应用内抛出的未捕获错误指定一个全局处理函数&#xff0c;它接收三个参数&#xff1a;错误对象、触发该错误的组件…