Java 转 C++ 那些事

2023-11-03

前提纪要

虽说编程语言只是承载思想的一种媒介,但是每种编程语言有自己的设计哲学,所以在实现自己思想的时候,也需要遵循该门语言的理念才行。截止 2022 年 07 月 12 日本人最大的体验是,Java 这门语言存在大量的过度封装(所以能封装成类就封装成类),C++ 这门语言有不少奇技淫巧(所以各种奇怪的茴香豆五种写法),所以编程体验差异很大。本文主要描述了 Java 程序员转 C++ 程序员写代码时那些不习惯的开发方式。
结果是对的,但它可能是不对的。

基础设施非常不完善

Java 中的包管理工具有 Maven, Gradle 等,但是 C++ 就一个 CMake(还有 Blade),对于引入的包的版本管理就是个空白,想要更新依赖的包,那就必须重新下载源码,重新编译。

变量生命周期短的可以

C++ 变量的生命周期非常短,出了{} 往往就意味着生命周期结束了(除非是使用 new 在堆上定义一个对象)。最危险的莫过于返回了局部对象的引用或者指针。

int64_t* test1() {
  int64_t arr[] = {1, 3, 5};
  return arr;    
}

int64_t* p = test1();

这样的写法,在 Java 中是没有问题的,但是 C++ 中就会出现结果不符合预期的情况(不会报错),原因就是 arr 是定义在函数内的局部变量,一旦 return 之后就释放掉了。
但是呢,返回一个值是对的(这个值即是个对象也行,未使用 new)

int test1() {
  int64_t p = 1;
  return p;
}
int num = test1();

这倒不是因为变量 p 的生命周期延长了,而是将临时变量 p 的结果通过拷贝的形式赋值给了 num。所以这里就引入了一个非常细节的问题,如果返回的是个对象,那么这个对象对应的类应该实现了拷贝构造函数来支持深拷贝,不然结果最后在函数外使用该临时变量的结果可能会不符合预期。对于 C++ 的基本类型,值拷贝一般也不会出什么问题。这里需要注意 Return Value Optimization(RVO),它可能让中间的表现形式看起来不是自己想的那样(比如不会调用拷贝构造函数之类的)。
函数返回值类型越简单越好
C++ 的返回值一般不会使用对象返回(除非该对象非常简单,函数逻辑同样非常简单)。

uint64_t Encrypt(Request& request, Response& response) {
  ...
  return 0;
}

C++ 一般会写成上述风格,但是 Java 一般会写成下述风格。

public Response Encrypt(Request request) {
  Response resp = new Response();
  ...
  return resp;
}

函数传递的参数既是参数也是结果

C++ 的参数一般使用指针或者引用传递参数,很少使用值传递的方式来传参,除非确定值传参的性能会更高。不过指针和引用都能避免传递参数的拷贝,有时抉择使用哪个还挺难办的,目前个人更倾向入参使用引用,出参使用指针。当然 Java 中的对象传值都是引用的方式,所以这种形式也天然支持,不过就个人历史经验而言,很少见到这种形式的写法。

uint64_t Encrypt(Request& request, Response* response) {
  ...
  return 0;
}

定义对象更加侧重充血模型

Java 项目中,尤其 Web 项目中,一般会以定义贫血模型为主(部分项目也会定义充血模型,尤其社区项目),C++ 中几乎很难看到贫血模型的定义方式。

封装应量力而行

虽然说 C++/Java 都是一种面向对象的语言,如果写过 Java Web 的话,会习惯性的各种封装以贴合 MVC 模式,C++ 就不是非常的在意这一套了,能使用基本参数的,几乎都会以基本参数优先。(如果参数多于 6 个再考虑将这些参数封装成类进行传递)。

void query(uint64_t stu_id, std::string name) {
  // do something
}

C++ 大概会写成上述这样,但是 Java 更侧重下述写法。

public class StuModel {
  int id;
  String name;
}

public void query(StuModel model) {
  // do something
}

异常可没那么流行
C++ 提供了异常机制,不过大家并不怎么会使用它。C++ 中一般返回错误码的形式来处理考虑不周到的情况,

Errorcode test() {
  // some function
  if (error) {
    return Errorcode::FAILED_MSG;
  }
  return Errorcode::OK;
}

C++ 一般习惯上述写法,但是对于 Java 一般习惯下述写法。

public void test() {
  try {
    // some functions
  } catch (RunTimeException e) {
    throw new ByteDanceCustomException("error cause", e);
  }
}

不兴 get/set 函数

Java 中对于类的属性一般会定义为私有,然后调用 get/set 函数来对其访问,但是 C++ 一般会直接将该属性定义为公有。

class Stu {
public:
  uint64_t id;
  std::string name;
}

Stu stu;
stu.id = 1;
stu.name = "zhang"

std::cout << stu.id << stu.name << std::endl;

C++ 会写成上述形式,但是 Java 更侧重写成下述形式。

public class Stu {
  public getId() {
    return id;
  }
  
  public setId(int id) {
    this.id = id;
  }
  
  ...

  private int id;
  private String name;
}

Stu stu = new Stu();
stu.setId(1);
System.out.println(stu.getId() + stu.getName());

构造函数不添加初始化逻辑

Java 的构造函数中一般会添加不少的初始化逻辑,在开源的项目中经常能看到这样的写法。C++ 当然也可以这么写,但是大家平时不会这么写。

class Encrypto {
public:
  Encrypto() = default;
  
  Init();
}

// Encrypto encrypto;
// encrypto.Init();

C++ 大概会按照上述方式写,Java 则会按照下述方式写。

public class Encrypto {
  public Encrypto() {
    Init();
  }
  
  public void Init() {
    // do something
  }
}

// Encrypto encrypto = new Encrypto();

链式编程并不受宠爱

C++ 并不喜欢链式编程,所以下述的写法是对的,但是大家很少这么写。

class Stu {
public:
  Stu id(uint64_t id) {
    this->id_ = id;
    return *this;
  }
  
  Stu name(std::string name) {
    this->name_ = name;
    return *this;
  }
  
  Stu age(uint32_t age) {
    this->age_ = age;
    return *this;
  }
  
private:
  uint64_t id_;
  std::string name_;
  uing32_t age_;
}

// Stu stu;
// stu.id(1).name("bytedance").age(12);

Java 则比较喜欢下述写法,lombok 爱好者更甚。

public class Stu {
  public Stu() {}

  public Stu id(int id) {
    this.id = id;
    return this;
  }
  
  public Stu name(String name) {
    this.name = name;
    return this;
  }
  
  public Stu age(int age) {
    this.age = age;
    return this;
  }
  
  private int id;
  private String name;
  private int age;
}

// new Stu().id(1).name("bytedance").age(12);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 转 C++ 那些事 的相关文章

  • 如何在 Bean Validation 1.0 中构造 ConstraintViolationException?

    我对 javax validation API 感到困惑 我正在编写一个简单的测试来理解它 Sample sample new Sample Set
  • C# 编译器不会优化不必要的强制转换

    前几天 在写答案的时候这个问题 https stackoverflow com questions 2208315 why is any slower than contains在这里 关于溢出 我对 C 编译器感到有点惊讶 它没有按照我的
  • MFC:如何设置CEdit框的焦点?

    我正在开发我的第一个简单的 MFC 项目 但我正在努力解决一个问题 想要设置所有的焦点CEdit其中一个对话框中的框 我的想法是 当打开对话框时 焦点位于第一个编辑框上 然后使用 选项卡 在它们之间交换 我看到了方法SetFocus 但我无
  • 使用具有抗锯齿功能的 C# 更改抗锯齿图像的背景颜色

    我有一个图像需要更改背景颜色 例如 将下面示例图像的背景更改为蓝色 然而 图像是抗锯齿的 所以我不能简单地用不同的颜色替换背景颜色 我尝试过的一种方法是创建第二个图像 仅作为背景 并更改其颜色并将两个图像合并为一个图像 但是这不起作用 因为
  • 引用/指针失效到底是什么?

    我找不到任何定义指针 引用无效在标准中 我问这个问题是因为我刚刚发现 C 11 禁止字符串的写时复制 COW 据我了解 如果应用了 COW 那么p仍然是一个有效的指针并且r以下命令后的有效参考 std string s abc std st
  • 从BackgroundWorker线程更新图像UI属性

    在我正在编写的 WPF 应用程序中 我有一个 TransformedBitmap 属性 该属性绑定到 UI 上的 Image 对象 每当我更改此属性时 图像就会更新 因此显示在屏幕上的图像也会更新 为了防止在检索下一张图像时 UI 冻结或变
  • Java和手动执行finalize

    如果我打电话finalize 在我的程序代码中的一个对象上 JVM当垃圾收集器处理这个对象时仍然再次运行该方法吗 这是一个大概的例子 MyObject m new MyObject m finalize m null System gc 是
  • Linux mremap 不释放旧映射?

    我需要一种方法将页面从一个虚拟地址范围复制到另一个虚拟地址范围 而无需实际复制数据 范围很大 延迟很重要 mremap 可以做到这一点 但问题是它也会删除旧的映射 由于我需要在多线程环境中执行此操作 因此我需要旧映射能够同时使用 因此稍后当
  • 逆向工程 ASP.NET Web 应用程序

    我有一个 ASP NET Web 应用程序 我没有源代码 该 bin 包含 10 个程序集和一个 compiled 文件 我在 App Code dll 上使用 Reflector 它向我显示了类和命名空间之类的东西 但它太混乱了 有没有什
  • 传递 Android DialogFragment 参数时,onCreateDialog 捆绑参数意外为 null

    我正在尝试使用 DialogFragment 在 Android 中显示一个基本对话框 并使用对话框消息的参数 如中所述StackOverflow线程 https stackoverflow com questions 15459209 p
  • 使用 jQuery 从 ASP.Net JSON 服务获取数据

    我正在尝试调用 Google 地图地理编码 API 从纬度 经度对中获取格式化的地址 然后将其记录到控制台 我正在尝试获取为给定位置返回的第一个 formatted address 项目 我很简单无法从 JSON 中提取该项目 我不知道为什
  • CUDA 8 编译错误 -std=gnu++11

    我正在尝试转换一些代码以使用 CUDA 并且我认为我遇到了兼容性问题 我们使用CMake 这些是我使用的 gcc 和 CUDA 版本 gcc version gcc Ubuntu 5 4 0 6ubuntu1 16 04 5 5 4 0 2
  • 如何清理 Runtime.exec() 中使用的用户输入?

    我需要通过命令行调用自定义脚本 这些脚本需要很少的参数并在 Linux 机器上调用 当前版本容易出现各种shell注入 如何清理用户给出的参数 参数包括登录名和路径 Unix 或 Windows 路径 用户应该能够输入任何可能的路径 该路径
  • 为什么我不能将 Collection 转换为 Collection>

    问题的关键是 为什么这会导致编译时错误 List
  • Jackson 反序列化相当于 @JsonUnwrapped 吗?

    假设我有以下课程 public class Parent public int age JsonUnwrapped public Name name 生成 JSON age 18 first Joey last Sixpack 我如何将其反
  • Android Google 地图无法在当前主题中找到样式“mapViewStyle”

    添加谷歌地图视图时 我扩展了MapView 使用xml编辑器将其添加到活动中 并将我的谷歌地图api密钥手动添加到布局xml文件中 我的权限在清单文件中允许互联网 我想知道的是 在 xml 编辑器中 我收到错误 无法在当前主题中找到样式 m
  • 如何使用 Jest 从 ElasticSearch 获取索引列表

    我正在尝试使用 Jest 检索索引列表 但我只得到 Stats statistics new Stats Builder build result client execute statistics 如何从结果中检索索引列表 除了统计之外
  • 使用 AmazonSNSClient 发送短信时的授权

    aws 官方文档如何发送短信 http docs aws amazon com sns latest dg sms publish to phone html使用 java 中的 aws SDK 非常简单 但是 当发送如底部示例所示的消息时
  • 如何将 SQL“LIKE”与 LINQ to Entities 结合使用?

    我有一个文本框 允许用户指定搜索字符串 包括通配符 例如 Joh Johnson mit ack on 在使用 LINQ to Entities 之前 我有一个存储过程 该存储过程将该字符串作为参数并执行以下操作 SELECT FROM T
  • 如何使用placement new重新初始化该字段?

    我的课程包含字段 private OrderUpdate curOrderUpdate 我一遍又一遍地使用它 经常需要重新初始化 for int i 0 i lt entries size i auto entry entries i ne

随机推荐

  • 软件显示获取服务器更新失败,闪耀暖暖获取更新服务器失败的解决方法

    今天是闪耀暖暖国服正式上线的日子 很多玩家都想第一时间进入游戏试玩 但是频繁有玩家出现网络连接失败的提示 这可愁坏了很多玩家 那么出现这个问题我们要怎么解决呢 下面就跟我一起来看看闪耀暖暖获取更新服务器失败的解决方法吧 一 官方服务器超载
  • unzip 错误 checkdir error: cannot create ctchain

    在mac中用unzip命令解压时出现下面错误 may Desktop SO unzip chain zip Archive chain zip checkdir error cannot create ctchain Illegal byt
  • 函数(1)

    目录 一 函数是什么 二 函数的分类 库函数 自定义函数 三 函数的参数 实际参数 实参 形式参数 形参 四 函数的调用 传值调用 传址调用 五 结束语 本章需要了解的重点主要包括以下几点 1 函数是什么 2 库函数 3 自定义函数 4 函
  • Day123.ElasticSearch:CAP定理、集群搭建、架构原理及分片、倒排索引、面试题

    目录 一 CAP定理 二 ES集群 1 搭建集群 2 head 插件安装 3 集群测试 4 核心概念 二 架构原理及分片 一 ElasticSearch 分片 二 分片控制 三 分片原理 1 倒排索引 2 文档搜索 3 近实时搜索 缓存传递
  • Vue组件缓存之keep-alive正确使用姿势

    先来看一个项目中的需求 作为苦逼的前端开发者 我们无时无刻都要面对产品经理提的各种需求 比如下图这个场景 场景 从首页的点击导航进入列表页 列表页点击列表进入 该 数据详情页 从详情页返回 希望列表页缓存 不重新渲染数据 这样会提高用户体验
  • ROCKCHIP-Rv1126安装ARM64-ARCH-ARM-DEBIAN系统

    1 deboot qemu arm debian 64位 内核文件系统 安装依赖软件 sudo apt get install debian archive keyring gcc aarch64 linux gnu bison flex
  • 锁->分布式锁->准实时方案

    概述 并发量由低到高 单机到集群 java对锁 分布式锁 准实时方案的概要实现 全文以商品抢购为例 目录 1 锁 2 分布式锁 2 1高可用 2 2性能调优 3 准实时方案 3 1性能提升 3 2高可用 正文 1 锁 lock和synchr
  • qt 交叉编译后 无libqxcb_QT5.5.1 + OpenGL 交叉编译

    概述 要使用Qt的quick相关功能则需要编译opengl opengl使用的是mesa 其依赖 libdrm libxcb libudev libxcb依赖 x11 xcb proto libxcb 编译 libdrm编译 CC arm
  • 图解通信原理与案例分析-4:“烽火连三月“看烽火通信背后的通信原理

    引言 杜甫 春望 国破山河在 城春草木深 感时花溅泪 恨别鸟惊心 烽火连三月 家书抵万金 白头搔更短 浑欲不胜簪 简单的几句诗歌 透析了在古代 人与人之间远距离通信的需求和相应的通信方式以及古人远程通信的困难 这里提及了两种通信 一种是烽火
  • cpu 原子操作的多核扩展性

    多核编程常用锁避免多个线程在修改同一个数据时产生race condition 当锁成为性能瓶颈时 我们又总想试着绕开它 而不可避免地接触了原子指令 但在实践中 用原子指令写出正确的代码是一件非常困难的事 琢磨不透的race conditio
  • 秋招结束

    2018 11 02 书和时间竟然都没有白费 最后还是拿到了前端开发的offer 怎么说呢 好像大家都不是凭借技术而是学历拿到的offer 自己还是知道自己有多少东西不懂不明白 实验室里 大家好像都知道自己秋招结束后要学什么做什么 我却有点
  • 后端写的前端页面怎么发送数据给后端,以及解决跨域问题

    在写前端的时候 因为主要是学的后端 所以前端知识非常不牢 经常在网上找文章 但他们的方法能解决他们的问题 不能解决我的 所以很长一段时间被怎么发送数据给难住 学了AJAX和axios又学的一知半解 写的代码还是不行 所以呢 我很推荐Chat
  • 【PB】PB调用WebService

    不管是用VS开发的基于 NET的WebService 还是用Java开发的WebService 还是用PB本身开发的 NET Web Service PB调用WebService的原理是一样的 都是通过WSDL访问WebServices 具
  • 为什么日志系统普遍用标准错误输出stderr?而不是标准输出stdcout?

    因为stderr是不带缓冲的 每个输出都会立即flush 而stdout是行缓冲的 要等到缓冲满了才flush 或者手动调fflush 前者更符合作为日志的需要 不然你程序执行过程中core了 缓冲里的遗言可能就丢了 而丢掉的往往是最接近出
  • Python和OpenCV视觉图像处理

    特点 OpenCV 3 是用于计算机视觉 机器学习和图像处理的原生跨平台库 OpenCV 方便的高级 API 隐藏了非常强大的内部结构 旨在提高计算效率 可以利用多核和 GPU 处理 学习如何通过操作像素来处理图像并使用直方图分析图像 展示
  • 第14.13节 BeautifulSoup的其他功能导览

    前面 第14 9节 Python中使用urllib request BeautifulSoup获取url访问的基本信息 第14 10节 Python中使用BeautifulSoup解析http报文 html标签相关属性的访问 和 第14 1
  • Python pandas数据分析:电商客户价值分析

    嗨害大家好鸭 我是芝士 1 RFM 客户价值模型介绍 RFM模型是衡量客户价值和客户创造利益能力的重要工具和手段 在众多的客户关系管理 CRM 的分析模式中 RFM模型是被广泛提到的 该机械模型通过一个客户的近期购买行为 购买的总体频率以及
  • nodejs 读取文件中的几行

    最近遇到了这样的问题 如何每次从一个文件里面依次读里面的几行 对nodejs提供的readline和一些三方npm例如lineReader不满意 就自己实现一个简易版本 var fs require fs var data fs readF
  • Spark服务启动的一些总结

    1 我理解常用的Spark部署方式有三种 1 本地服务 就是所谓的local 在IDE上本地跑程序 用于调试 2 Standalone 使用自己的master worker进行服务的调度 脱离yarn的资源管理 3 Spark on yar
  • Java 转 C++ 那些事

    前提纪要 虽说编程语言只是承载思想的一种媒介 但是每种编程语言有自己的设计哲学 所以在实现自己思想的时候 也需要遵循该门语言的理念才行 截止 2022 年 07 月 12 日本人最大的体验是 Java 这门语言存在大量的过度封装 所以能封装