前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >openFoam源码中的C++

openFoam源码中的C++

作者头像
gzq大数据
发布于 2021-08-06 06:36:09
发布于 2021-08-06 06:36:09
96500
代码可运行
举报
文章被收录于专栏:大数据那些事大数据那些事
运行总次数:0
代码可运行

openFoam源码中涉及到的c++思想有很多,因为在计算流体力学中,域的创建尤为重要,我们可以在域中存储我们想要的物理变量如速度、压力等等。 首先:有一个宏观上的思维,我们用的大多数域对应的C++类是GeometricField,这个类里面包含了很多信息,但他的Base类其实是Field这个类,可以用下图来表示这个关系:

分析

当然,一切要从代码看起: 首先看Field基类,找到Filed的.C和.H头文件开始分析: 该类都是在Foam这个大的命名空间底下,下面定义了很多模板类。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<class Type>
class Field;

//- Pre-declare related SubField type
template<class Type>
class SubField;

template<class Type>
void writeEntry(Ostream& os, const Field<Type>&);

template<class Type>
Ostream& operator<<(Ostream&, const Field<Type>&);

template<class Type>
Ostream& operator<<(Ostream&, const tmp<Field<Type>>&);
// 类的前置声明
class dictionary;

这里用到了很多模板类的语法,首先声明了两个模板类的前置声明Field以及SubField,在这里要注意的是为什么要进行前置声明:

由于某些原因不方便在头文件中直接引入另一个模板类的头文件,但声明变量是需要用到该模板类型,这时候就要用到模板类的前置声明

可以看到操作符重载的参数列表里用到了Field<Type>,这就必须进行前置声明,可能此时大家又有疑问,为什么操作符的重载也要进行前置声明呢,这是可以看到在Filed这个大的模板类里有这样一段友元函数的声明:

有这样一条规定:友元函数和运算符的前向声明:如果一个模板类里调用了友元函数(外面定义的方法可以使用该类里面的私有变量),而且这个友元函数里面的参数还用到了这个模板类,那么就得提前以模板的方式去声明这个类和函数。 这样大家就懂了头文件里前面这几行的声明的必要性。下面再看这个Filed类模板里面的一些难以理解的C++代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Field:public tmp<Field<Type>>::refCount,public List<Type>

首先我们看到这里的Filed继承了List,相当于我们的Filed里面存储方式为一维数组的存储。 下面定义了一个copy函数:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 const UList<Type>& copySelf(const UList<Type>& mapF,tmp<Field<Type>>& tmapFcpy) const;

这里看到前后都有一个const:前面的const好理解说明这个指针不能被改变,最后这const用于修饰该函数,表示在函数内不能改变其对应对象的成员变量的值。 接下来的typedef是用来声明两个类型的,第一个typename的作用是给编译器强调后面跟的是一个类型。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
typedef typename pTraits<Type>::cmptType cmptType;
typedef SubField<Type> subField;

下来该类又使用了一个内联函数, 为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,只是建议内联不代表编译器真的会执行

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 inline static const Field<Type>& null()
        {
            return NullObjectRef<Field<Type>>();
        }

下来定义了一些该类的构造器,其中比较有意思的是:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
explicit Field(const label);

这里explict的解释我总结如下: C++中的explicit关键字只能用于修饰只有一个参数的类构造函数, 它的作用是表明该构造函数是显示的, 而非隐式的, 跟它相对应的 另一个关键字是implicit, 意思是隐藏的,类构造函数默认情况下即声明为 implicit(隐式).explicit声明之后,外面调用该构造函数必须显式声明, 因为构造器若只有一个参数并且默认是implicit,在外面调用的时候可以直接等于…, 编译器会自动给你补全,这样很容易产生歧义 例子: A(int size){ …构造函数里面的变量 } 外面调用可以直接A = 10;但是这个10并不代表size,不伦不类 接下来,该类还使用了一些复制构造函数,这都是我们平常开发不经常使用的操作:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Field(const Field<Type>&);

        //- Copy constructor or re-use as specified.
        Field(Field<Type>&, bool reuse);

        //- Move constructor transferring the Field contents
        Field(Field<Type>&&);

        //- Copy constructor of tmp<Field>
        Field(const tmp<Field<Type>>&);

复制构造函数的解释: 如果类的设计者不写复制构造函数, 编译器就会自动生成复制构造函数。 大多数情况下,其作用是实现从源对象到目标对象逐个字节的复制, 即使得目标对象的每个成员变量都变得和源对象相等。 在.C文件中,我们也可以看见一些有意思的写法,比如说模板构造函数,成员变量的直接初始化等等:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
const char* const Foam::Field<Type>::typeName("Field");
Foam::Field<Type>::Field(): List<Type>(){}

看懂了这个文件,在相应的找到DimensionedField和GeometricField就可以看出他们之间的继承和每次继承完以后新添的一些功能创造出了一个GeometricField这样包含很多信息的域类。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/08/05 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
【C++】泛型编程 ⑮ ( 类模板示例 - 数组类模板 | 自定义类中持有指针成员变量 )
在上一篇博客 中 , 定义了 可拷贝 与 可打印 的 自定义类 Student , 可以被存放到 数组类模板 中 ;
韩曙亮
2023/11/25
3410
【C++】泛型编程 ⑮ ( 类模板示例 - 数组类模板 | 自定义类中持有指针成员变量 )
【C++】泛型编程 ⑪ ( 类模板的运算符重载 - 函数实现 写在类外部的不同的 .h 头文件和 .cpp 代码中 )
在博客 【C++】泛型编程 ⑨ ( 类模板的运算符重载 - 函数声明 和 函数实现 写在同一个类中 | 类模板 的 外部友元函数问题 ) 中实现了第一种情况 , 类模板 的 函数声明 与 函数实现 都写在同一个类中 , 也就是没有分开进行编码 ;
韩曙亮
2023/11/23
4360
【C++】泛型编程 ⑪ ( 类模板的运算符重载 - 函数实现 写在类外部的不同的 .h 头文件和 .cpp 代码中 )
【C++】泛型编程 ⑬ ( 类模板示例 - 数组类模板 | 构造函数和析构函数 的 声明与实现 | 普通成员函数 的 声明与实现 | 外部友元函数 的 声明与实现 )
本篇博客中 开始 使用 类模板 开发一个 数组类 , 数组 中 可以维护 不同类型的 元素数据 , 如 : int , char , 自定义类 ;
韩曙亮
2023/11/24
7310
【C++】泛型编程 ⑬ ( 类模板示例 - 数组类模板 | 构造函数和析构函数 的 声明与实现 | 普通成员函数 的 声明与实现 | 外部友元函数 的 声明与实现 )
【C++】泛型编程 ⑭ ( 类模板示例 - 数组类模板 | 容器思想 | 自定义类可拷贝 - 深拷贝与浅拷贝 | 自定义类可打印 - 左移运算符重载 )
上一篇博客 【C++】泛型编程 ⑬ ( 类模板示例 - 数组类模板 | 构造函数和析构函数 的 声明与实现 | 普通成员函数 的 声明与实现 | 外部友元函数 的 声明与实现 ) 中 , 实现了一个 数组 类模板 , 数组 中的 数据元素 是 泛型类型 , 可以是任意类型 ;
韩曙亮
2023/11/24
2630
【C++】泛型编程 ⑭ ( 类模板示例 - 数组类模板 | 容器思想 | 自定义类可拷贝 - 深拷贝与浅拷贝 | 自定义类可打印 - 左移运算符重载 )
C++心决之类和对象详解(下篇)(封装进阶篇)
虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,
一枕眠秋雨
2024/05/04
1150
C++模板知识点总结
函数模板就是建立一个通用的函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表。这个通用函数就称为函数模板。
半生瓜的blog
2023/05/12
2550
【C++】打怪升级——通关类和对象(下)
先了解一下本篇的学习目标:构造函数体赋值、初始化列表、explicit关键字 、static成员板块、C++11的成员初始化、友元以及内部类,同时还有匿名对象的介绍以及编译器优化的简单涉及。
平凡的人1
2022/11/15
2870
【C++】打怪升级——通关类和对象(下)
从入门到精通C++之类和对象(续)
在编程中,初始化列表是一种用于在创建对象时初始化成员变量的快捷方式。通过初始化列表,可以在对象构造时直接为成员变量赋值,而无需在构造函数体内进行赋值操作。这不仅使代码更简洁清晰,还可以提高程序的执行效率。
用户11305458
2024/10/09
740
从入门到精通C++之类和对象(续)
【C++】类和对象核心总结
a. 在C语言阶段我们就已经认识到了结构体,它可以帮助我们实现多种数据结构,功能强大不言而喻。在C++中为了更好的封装,以及更好的将现实生活抽象化为计算机世界,采用面向对象的思想帮助程序猿能够对用户需求进行抽象思维化,不得不需要类class的出现。
举杯邀明月
2023/04/12
8140
【C++】类和对象核心总结
【C++】类与对象【下】
初始化列表: 以一个冒号开始,接着以逗号分隔数据的成员列表,每个成员变量后面跟一个放在括号中的初始值或表达式,初始化完之后,结尾处要有一个“{}”的结束符号
用户11367452
2025/05/15
450
【C++】类与对象【下】
C++函数模板(模板函数)详解
大家好,又见面了,我是你们的朋友全栈君。 C++函数模板(模板函数)详解 定义 用法: 函数模板的原理 延申用法 2.1为什么需要类模板 2.2单个类模板语法 2.3继承中的类模板语法 案例1: 案例2: 2.4类模板的基础语法 2.5类模板语法知识体系梳理 1.所有的类模板函数写在类的内部 复数类: 2.所有的类模板函数写在类的外部,在一个cpp中 2.5总结 关于类模板的几点说明: 2.6类模板中的static关键字 案例2:以下来自:C++类模板遇上static关键字 2.7类模板在项目开发中的
全栈程序员站长
2022/07/22
2K0
C++函数模板(模板函数)详解
C++:20---类模板(template)
一、类模板与模板类 类模板:一个模板(是模板) 模板类:调用类模板生成的类对象(是类实体),也称为类模板的实例化 类模板的定义: 与函数模板的定义是一样的 template <typename T>class Blob{public:Blob();Blob(std::initializer_list<T> i);}; 模板类的使用: 在定义类时,使用到类名的地方都需要显示的给出模板类的类型,格式为<> int main(){Blob<int> ia;Blob<int> ia2 = { 1,2,3 };Bl
用户3479834
2021/02/03
1.3K0
多重收纳(类模板)C++
现在我们要制作一种盒子,它能够收纳多种类型的元素,比如int、double、char、string等等。
叶茂林
2023/07/30
2370
多重收纳(类模板)C++
【C++初阶】类和对象终极篇
我们知道在函数传参的时候,为了减少拷贝,所以我们一般选择传引用的方式,但是传引用有一个问题,假如我不想任何人在函数内部改引用值,从而改变实参.我们一般都会选择在引用的基础上加上const修饰,这样的话,有两个优点:
MicroFrank
2023/01/16
2530
C++之面向对象(下)
本文继续介绍与C++中与面向对象相关的内容,介绍了构造函数中的初始化列表、隐式类型转换、类的静态成员、友元、内部类、匿名对象以及编译器对拷贝构造的优化等概念。
摘星
2023/04/28
4190
C++之面向对象(下)
C++初阶-类和对象下
对于既有成员缺省值,又有默认构造函数(初始化列表和函数体赋值)时,对象创建时会先走初始化列表,再走函数体赋值,最后走成员缺省值
用户9645905
2022/11/30
3930
C++初阶-类和对象下
C++天使的灵动心跳代码:类和对象(下)
虽然上述构造函数调用之后,对象中已经有了一个初始值,但是不能将其称为对对象中成员变量的初始化,构造函数体中的语句只能将其称为赋初值,而不能称作初始化。因为初始化只能初始化一次,而构造函数体内可以多次赋值
DARLING Zero two
2024/12/24
670
【C++】类和对象(下篇)
在前两期的 类和对象(上篇) 和 类和对象(中篇) 我们学习了有关类和对象的大部分知识,这一篇我将会带大家完善这方面的有关知识,并完成我们日期类的完整实现。
YoungMLet
2024/03/01
1350
【C++】类和对象(下篇)
终于弄明白C++关键字了(2)
1.在函数比较多的情况下可以提示读者某个函数重写了基类虚函数(表示这 个虚函数是从基类继承,不是派生类自己定义的);
用户9831583
2022/06/16
6390
终于弄明白C++关键字了(2)
C++类与对象(下)
前面的内容中,我们学习了类与对象相关知识,这可以算是入门C++的第一道门槛,不过到了现在,相信大家或多或少都有了一定的知识储备与能力的提升。今天,就让我们进入类与对象的最后一部分知识点,开冲!
用户11289931
2024/09/24
1020
C++类与对象(下)
推荐阅读
相关推荐
【C++】泛型编程 ⑮ ( 类模板示例 - 数组类模板 | 自定义类中持有指针成员变量 )
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验