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

        本文主要介绍和记录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.hqwc.cn/news/188437.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafka学习笔记(一)

目录 第1章 Kafka概述1.1 消息队列&#xff08;Message Queue&#xff09;1.1.1 传统消息队列的应用场景1.1.2 消息队列的两种模式 1.2 定义 第2章 Kafka快速入门2.1 安装部署2.1.1 集群规划2.1.2 jar包下载2.1.3 集群部署 2.2 Kafka命令行操作 第3章 Kafka架构深入3.1 Kafka工…

蘑菇街获得mogujie商品详情 API 返回值说明

速卖通API接口是速卖通平台提供的一种数据交换接口&#xff0c;可以帮助卖家快速获取平台上的商品信息、订单信息、用户信息等数据&#xff0c;以便在自己的应用程序中进行展示、管理或分析。 速卖通API接口可以通过以下步骤进行使用&#xff1a; 注册速卖通账号并获取API密钥…

广州华锐互动VRAR:利用VR开展刑事案件公安取证培训,沉浸式体验提升实战能力

随着科技的飞速发展&#xff0c;虚拟现实(VR)技术为我们的生活和工作带来了前所未有的便利。近年来&#xff0c;VR技术在刑事案件公安取证培训中的应用逐渐显现出其独特优势。通过模拟真实的犯罪现场&#xff0c;VR技术为学员提供了沉浸式的体验&#xff0c;使他们在安全的环境…

vite+vue3+ts中watch和watchEffct的使用

vitevue3ts中watch和watchEffct的使用 本文目录 vitevue3ts中watch和watchEffct的使用watchrefreactivepropsimmediate组合监听 watchEffect单值多值侦听副作用停止监听 watch vue官方文档&#xff1a;https://cn.vuejs.org/api/reactivity-core.html#watch 可以监听基础类型&…

2023年【陕西省安全员B证】考试题库及陕西省安全员B证找解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 陕西省安全员B证考试题库是安全生产模拟考试一点通生成的&#xff0c;陕西省安全员B证证模拟考试题库是根据陕西省安全员B证最新版教材汇编出陕西省安全员B证仿真模拟考试。2023年【陕西省安全员B证】考试题库及陕西省…

修改YOLOv5的模型结构第二弹

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子 上节说到了通过修改YOLOv5的common.py来修改模型的结构&#xff0c;修改的是模块的内…

ArcGIS创建格网

目录 1、创建网格 2、裁剪边界外的网格 3、只保留边界内完整的网格 1、创建网格 首先&#xff0c;我们在创建渔网前&#xff0c;需要指定渔网覆盖的范围。这里我们就以四子王为例 在ArcMap软件中&#xff0c;我们依次选择“Toolboxes”→“Data Management Tools&#xff0…

vscode中vue项目引入的组件的颜色没区分解决办法

vscode中vue项目引入的组件的颜色没区分解决办法 图中引入组件和其他标签颜色一样没有区分&#xff0c;让开发者不易区分&#xff0c;很蓝瘦 这个就很直观&#xff0c;解决办法就是你当前的vscode版本不对&#xff0c;你得去找找其他版本&#xff0c;我的解决办法就是去官网历…

交易者最看重什么?anzo Capital这点最重要!

交易者最看重什么&#xff1f;有人会说技术&#xff0c;有人会说交易策略&#xff0c;有人会说盈利&#xff0c;但anzo Capital认为Vishal 最看重的应该是眼睛吧&#xff01; 29岁的Vishal Agraval在9年前因某种原因失去了视力&#xff0c;然而&#xff0c;他的失明并未能阻…

国内外优秀的六款项目管理软件推荐

在面对各种项目管理需求时&#xff0c;选择适合的软件非常重要&#xff0c;项目管理软件不但帮助项目经理更准确的把控项目进度&#xff0c;也使分布在各地的团队能够更高效地合作。 下面是国内外优秀的六款项目管理软件&#xff1a; 1、进度猫 进度猫作为国产项目进度管理…

Java-Review

题型分值总分分布简答 5 ∗ 8 ′ 5*8 5∗8′ 4 0 ′ 40 40′面向对象、异常处理、多线程、输入输出处理程序分析和补全 3 ∗ 1 0 ′ 3*10 3∗10′ 3 0 ′ 30 30′异常处理、Collection、图形化界面、输入输出处理编程 2 ∗ 1 5 ′ 2*15 2∗15′ 3 0 ′ 30 30′Collections、多线…

黑马React18: 基础Part 1

黑马React: 基础1 Date: November 15, 2023 Sum: React介绍、JSX、事件绑定、组件、useState、B站评论 React介绍 概念: React由Meta公司研发&#xff0c;是一个用于 构建Web和原生交互界面的库 优势: 1-组件化的开发方式 2-优秀的性能 3-丰富的生态 4-跨平台开发 开发环境搭…