C++中静态成员变量和普通成员变量、私有成员变量和公有成员变量的区别

news2024/10/7 14:29:25

        本文主要介绍和记录C++中静态成员变量和普通成员变量、私有成员变量和公有成员变量的区别,并给出相关示例程序,最后结合相关工程应用中编译报错给出报错原因及介绍思路

一、静态成员变量和普通成员变量

         C++中,静态成员变量和普通成员变量有一些重要的区别,如下所示:

1. 存储位置:


   普通成员变量: 每个类的对象都有自己的一份普通成员变量的拷贝,它们存储在对象的内存中。
   静态成员变量: 所有属于同一个类的对象共享同一份静态成员变量的拷贝,它存储在类的类体外,并且不依赖于类的实例。

2. 作用域:


   普通成员变量: 只有在类的实例化后,通过对象访问。
   静态成员变量: 可以通过类名直接访问,不需要创建类的实例。

3. 初始化:


  普通成员变量: 在每个对象被创建时进行初始化,可以在类的构造函数中进行。
  静态成员变量: 需要在类体外进行初始化,通常在类的实现文件中进行。

4. 生命周期:


   普通成员变量: 随着对象的创建而创建,随着对象的销毁而销毁。
    静态成员变量:从程序开始时创建,直到程序结束时销毁。

5. 访问权限:


    普通成员变量:可以是公有、私有或受保护的,根据访问修饰符的设置。
    静态成员变量: 也可以是公有、私有或受保护的,但由于可以通过类名直接访问,一般建议将其声明为私有,并提供公有的静态成员函数用于访问或修改。

6. 使用场景:


   普通成员变量: 通常用于描述对象的状态或属性。
   静态成员变量:通常用于描述属于整个类而非特定对象的属性,例如计数器、共享资源等。

        下面是一个简单的例子,演示了静态成员变量和普通成员变量的用法:

#include <iostream>

class MyClass {
public:
    int regularVar;        // 普通成员变量
    static int staticVar;  // 静态成员变量

    // 构造函数
    MyClass() {
        regularVar = 0;
    }

    // 静态成员函数,可以访问静态成员变量和其他静态成员函数
    static void staticFunction() {
        staticVar++;
    }
};

// 初始化静态成员变量
int MyClass::staticVar = 0;

int main() {
    MyClass obj1, obj2;

    obj1.regularVar = 10;
    obj2.regularVar = 20;

    // 访问普通成员变量,实例化后,通过对象访问
    std::cout << "Regular Variable of obj1: " << obj1.regularVar << std::endl;
    std::cout << "Regular Variable of obj2: " << obj2.regularVar << std::endl;

    // 访问静态成员变量,不需要实例化类的对象
    std::cout << "Static Variable: " << MyClass::staticVar << std::endl;

    // 调用静态成员函数
    MyClass::staticFunction();
    std::cout << "Static Variable after calling staticFunction: " << MyClass::staticVar << std::endl;

    return 0;
}

          这个程序创建了一个 MyClass 类,其中包含了一个普通成员变量 regularVar 和一个静态成员变量 staticVar。`regularVar`是普通成员变量,每个对象都有自己的副本。`staticVar` 是静态成员变量,所有对象共享同一个副本。

        在 main 函数中,创建了两个对象 obj1obj2,分别设置了它们的 regularVar 值。然后,分别通过类名和对象访问了静态成员变量和普通成员变量,并调用了静态成员函数来改变staticVar的值

        运行结果如下:

Regular Variable of obj1: 10
Regular Variable of obj2: 20
Static Variable: 0
Static Variable after calling staticFunction: 1

   

 二、私有成员变量和公有成员变量

        在C++中,私有成员变量和公有成员变量有以下主要区别:

1. 访问权限:


   - 私有成员变量: 只能在类的内部访问,外部代码无法直接访问。只有类的成员函数(包括私有成员函数和公有成员函数)可以访问私有成员。
   - 公有成员变量: 可以被类的外部代码直接访问,没有访问限制。

2. 封装性:


   - 私有成员变量:提供了更好的封装性,隐藏了类的实现细节,外部代码无法直接修改或访问私有成员。
   - 公有成员变量:破坏了封装性,外部代码可以直接修改公有成员,导致代码的不安全性和可维护性降低。

3. 安全性:


   - 私有成员变量: 提高了代码的安全性,防止外部代码意外地修改类的内部状态。
   - 公有成员变量:可能降低代码的安全性,因为外部代码可以直接修改类的公有成员。

4. 灵活性:


   - 私有成员变量: 允许类实现者更灵活地控制类的内部状态和行为,可以在类的内部进行适当的处理。
   - 公有成员变量: 提供了更直接的访问方式,但可能导致类的实现难以修改。

5. 继承和派生:


   - 私有成员变量:在派生类中不可直接访问基类的私有成员。
   - 公有成员变量:在派生类中可以直接访问基类的公有成员,但这同样可能导致破坏封装性。

        下面是一个简单的例子,演示了私有成员变量和公有成员变量的用法:

#include <iostream>

class Example {
private:
    int privateVar;  // 私有成员变量

public:
    int publicVar;   // 公有成员变量

    // 构造函数
    Example() {
        privateVar = 0;
        publicVar = 0;
    }

    // 成员函数访问私有成员
    void setPrivateVar(int value) {
        privateVar = value;
    }

    int getPrivateVar() const {
        return privateVar;
    }
};

int main() {
    Example obj;

    // 外部无法直接访问私有成员
    // obj.privateVar;  // 编译错误

    // 外部可以直接访问公有成员
    obj.publicVar = 42;

    // 调用成员函数访问私有成员
    obj.setPrivateVar(10);
    int privateValue = obj.getPrivateVar();

    // 输出结果
    std::cout << "Public Variable: " << obj.publicVar << std::endl;
    std::cout << "Private Variable: " << privateValue << std::endl;

    return 0;
}

        在上述示例中,`privateVar` 是私有成员变量,只能通过成员函数进行访问,而`publicVar` 是公有成员变量,可以直接在外部访问。

        运行结果如下:

Public Variable: 42
Private Variable: 10

 三、相关编译报错原因及解决方法

        1、编译报错内容如下:

/home/gly/catkin_ws/src/navigation-noetic-devel/rrt_star_global_planner-main/src/traj_optimizer.cpp:1066:9: error: invalid use of member ‘Trajectory_optimization::BsplineOptimizer::Opt_Storage’ in static member function
 1066 |         Opt_Storage.save_vector_T(opt_base_path,FN_2,time_consuming);
      |         ^~~~~~~~~~~
In file included from /home/gly/catkin_ws/src/navigation-noetic-devel/rrt_star_global_planner-main/src/traj_optimizer.cpp:1:
/home/gly/catkin_ws/src/navigation-noetic-devel/rrt_star_global_planner-main/include/rrt_star_global_planner/traj_optimizer.h:66:37: note: declared here
   66 |       Data_Storage::FileDataStorage Opt_Storage; //创建FileDataStorage类的实例,取名为Mpc_Storage
 

        2、报错原因分析:

        我们以第一个报错为例进行介绍,报错原因是在类中创建了普通成员Opt_Storage,然后尝试在类的静态成员函数 costFunctionCallback 中直接调用类的该普通成员Opt_Storage,导致报错

        因为,静态函数无法直接访问非静态成员!!!

        3、解决方案:

        有三种解决思路,第一种costFunctionCallback 设计成非静态成员函数,这样它就可以访问实例的成员变量。此时,在该函数中直接使用以下语句就不会产生报错了

Opt_Storage.save_vector_T(opt_base_path,FN_2,time_consuming);

       如果我们需要保留 costFunctionCallback函数为静态成员函数,则可以采用第二种方案,使用实例化的类的对象来调用该成员,此时,上述语句需要改写成以下的形式

//由于costFunctionCallback是静态成员函数,而静态函数无法直接访问非静态成员
//需要借助类的实例来访问
Trajectory_optimization::BsplineOptimizer temporary_object;
    
temporary_object.Opt_Storage.save_vector_T(temporary_object.opt_base_path,temporary_object.FN_2,time_consuming); 

        如果我们需要保留 costFunctionCallback函数为静态成员函数,除了上面的第二种方案,还有第三种解决方案,即将想要在costFunctionCallback函数中直接调用的相关成员,由普通成员更改为静态成员,并在类中声明,在类外对其进行初始化。

   最终,因为我需要保留costFunctionCallback函数为静态成员函数,且为了方便的通过修改类所在的h文件来对相关参数进行设定,不想采用类内声明,类外初始化的形式,所以放弃了第一种和第三种方案,采用了第二种方案,编译成功

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

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

相关文章

SpringBoot+Vue3+MySQL集群 开发健康体检双系统

第1章 课程介绍 试看4 节 | 38分钟 观看项目演示&#xff0c;熟悉大健康体检项目主要功能。掌握学习本课程的最佳方法&#xff0c;以及如何利用在线手册学习和答疑。 收起列表 视频&#xff1a; 1-1 导学 (22:46) 试看 视频&#xff1a; 1-2 学习方法注意事项 (07:46) 视频&am…

chromium通信系统-mojo系统(一)-ipcz系统基本概念

ipcz 是chromium的跨进程通信系统。z可能是代表zero&#xff0c;表示0拷贝通信。 chromium的文档是非常丰富的&#xff0c;关于ipcz最重要的一篇官方文档是IPCZ。 关于ipcz本篇文章主要的目的是通过源代码去分析它的实现。再进入分析前我们先对官方文档做一个总结&#xff0c;…

北邮22级信通院数电:Verilog-FPGA(9)第九周实验(3)实现一个具有清零功能的按键计数器,对按键进行计数并显示

北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章&#xff0c;请访问专栏&#xff1a; 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 一.代码部分 1.1 counter.v 1.2 debounce.v …

MIKE水动力笔记20_由dfs2网格文件提取dfs1断面序列文件

本文目录 前言Step 1 MIKE Zero工具箱Step 2 提取dfs1 前言 在MIKE中&#xff0c;dfs2是一个一个小格格的网格面的时间序列文件&#xff0c;dfs1是一条由多个点组成的线的时间序列文件。 如下两图&#xff1a; 本博文内容主要讲如何从dfs2网格文件中提取dfs1断面序列文件。 …

大数据Doris(二十五):数据导入演示和其他导入案例

文章目录 数据导入演示和其他导入案例 一、数据导入演示

jvm 内存结构 ^_^

1. 程序计数器 2. 虚拟机栈 3. 本地方法栈 4. 堆 5. 方法区 程序计数器 定义&#xff1a; Program Counter Register 程序计数器&#xff08;寄存器&#xff09; 作用&#xff0c;是记住下一条jvm指令的执行地址 特点&#xff1a; 是线程私有的 不会存在内存溢出 虚拟机栈…

【MATLAB源码-第81期】基于matlab的polar码三种译码算法比较(SC,SCL,BP)。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 Polar码&#xff08;Polar Codes&#xff09;是一种前向纠错编码方法&#xff0c;被认为是实现信道容量极限的编码方法之一。它在某些场合下&#xff0c;如5G通信标准中得到了应用。Polar码的主要译码算法包括Successive Can…

Flutter 应用启动从闪屏页短暂黑屏再到第一个页面

由于应用初始状态启动会有白屏现象&#xff0c;便使用 flutter_native_splash 2.3.5 插件生成了启动相关的配置&#xff0c;并且按照示例使用了 import package:flutter_native_splash/flutter_native_splash.dart;void main() {WidgetsBinding widgetsBinding WidgetsFlutte…

【SAP-ABAP】--MRKO隐式增强字段步骤

业务需求&#xff1a;给MRKO增加几个增强字段 给标准表进行增强 1.如果标准表或者结构&#xff0c;带CL_***&#xff0c;一般表示SAP预留的增强位置&#xff0c;可以 直接双击这个类型&#xff0c;点击创建&#xff0c;然后直接在预留的结构里面添加自己 需要增加的字段 2.如…

MySQL事务特性原理

文章目录 事务四特性预备知识checkpoint机制redo日志redo的流程事务提交后什么时候进行刷盘 undo日志&#xff1a;数据还未被修改、也是备份Undo日志的作用undo的存储结构回滚段与事务回滚段中的数据分类undo的类型undo log的生命周期 MVCC一、 原子性原理如何通过undo日志实现…

001.HCIA_网络基本概念

1、网络历史 网络历史——数通为什么产生? 1946年:世界上第一台计算机诞生。军事科研--高速运算 1962年:古巴导弹危机 1969年:美国国防部高级研究计划署ARPA“巨型网络”--ARPAnet 阿帕网 厂商垄断——不能大规模普及 IBM 每个厂商都单独定义标准 问题:网络没有标准 1…

QMenuBar和QToolBar使用同一个QAction

文章目录 前言一、编辑QMenuBar二、将QMenuBar中的Action添加到toolbar总结 前言 qmenubar中的action添加到toolbar&#xff0c;不是在toolbar中再添加action&#xff0c;效果图如下 一、编辑QMenuBar 正常编辑QMenuBar&#xff0c;以下图为例 二、将QMenuBar中的Action添…

双极性集成电路芯片 D7312,可用于小型收录机中作前置放大电路。电源开关冲击噪音小、 反应快

一块双极性集成电路芯片 D7312。可用于小型收录机中作前置放大电路。 主要特点&#xff1a; ● 含ALC电路和ALC检波电路。 ● 外接元件少。 ● 增益高&#xff0c;噪声低。 ● 静态电流小 ● 电源开关冲击噪音小、 反应快 ● 具有过热保护功能 …

本地生活视频号团购怎么做?一部分人已经吃到红利!

重磅消息&#xff01;视频号本地生活团购上线了&#xff01;作为新的流量聚集地&#xff0c;视频号通过带货达人、商家、团购商品三者在微信平台提升了更多的曝光量与转化率&#xff0c;同时在短视频挂载、直播挂载的基础上&#xff0c;实现了视频号团购的交易闭环&#xff0c;…

VSCode 运行java程序中文乱码

现象描述 java文件中包含中文&#xff0c;运行java程序后&#xff0c;乱码报错。 解决方法 原本运行指令为 cd "d:\programProjects\Java_proj\" ; if ($?) { javac Solution.java } ; if ($?) { java Solution } 需要添加 编码格式 -encoding utf8 cd &quo…

企业防泄密软件——域之盾软件

在当今这个数字化时代&#xff0c;信息的安全性变得越来越重要。对于企业而言&#xff0c;保护核心信息不被泄露显得尤为重要。域之盾软件作为企业防泄密软件&#xff0c;旨在为企业提供全方位的信息安全保障。 其具有出色的防护功能&#xff0c;能够有效地防止企业内部信息泄露…

Linux输入设备应用编程(键盘,按键,触摸屏,鼠标)

目录 一 输入设备编程介绍 1.1 什么是输入设备呢&#xff1f; 1.2 什么是输入设备的应用编程&#xff1f; 1.3 input子系统 1.4 数据读取流程 1.5 应用程序如何解析数据 1.5.1 按键类事件&#xff1a; 1.5.2 相对位移事件 1.5.3 绝对位移事件 二 读取 struct input_e…

使用Microsoft Dynamics AX 2012 - 2. 入门:导航和常规选项

Microsoft Dynamics AX的核心原则之一是为习惯于Microsoft软件的用户提供熟悉的外观和感觉。然而&#xff0c;业务软件必须适应业务流程&#xff0c;这可能相当复杂。 用户界面和常见任务 在我们开始进行业务流程和案例研究之前&#xff0c;我们想了解一下本章中的常见功能。…

linux 查看命令使用说明

查看命令的使用说明的命令有三种&#xff0c;但并不是每个命令都可以使用这三种命令去查看某个命令的使用说明&#xff0c;如果一种不行就使用另外一种试一试。 1.whatis 命令 概括命令的作用 2.命令 --help 命令的使用格式和选项的作用 3.man 命令 命令的作用和选项的详细…

小白必看,接口测试神器 Jmeter 如何实现测试关联

明年三四月份赶上跳槽高峰期&#xff0c;面试中&#xff0c;接口测试部分的关联是经常被提及的知识点之一&#xff0c;经常有同学因此错失良机&#xff0c;“关联”可谓是重中之重了&#xff0c;今天就写一篇关于Jmeter关联的文章&#xff0c;以作备忘。 所谓关联&#xff0c;…