solve函数为啥不需要用对象去访问调用?



  • 微信图片_20210422152445.png

    图片的内容是icoFoam.C。想请教下,solve函数不是fvMatrix的成员函数吗,调用成员函数不是应该用对象去访问吗?为什么可以直接用函数名调用呢。就算是静态成员函数,不也应该用类的名字调用吗,请问这里是什么用法?谢谢!



  • 可以这么理解,C++是采用面向对象的编程语言,但是也不是说就不能用面向过程编程。具体可以看东岳老师写的文章,非常详细。
    https://www.cfd-china.com/topic/1172/你要的openfoam编程杂七杂八

    http://dyfluid.com/docs/book/_book/chapter1/section2.html

    这段代码可以这么改:

            fvVectorMatrix UEqn
            (
                fvm::ddt(U)
              + fvm::div(phi, U)
              - fvm::laplacian(nu, U)
              == -fvc::grad(p)
            );
    
            if (piso.momentumPredictor())
            {
                UEqn.solve();
            }
    

    编译没问题,运行了几步就报错了。



  • @wangfei9088 谢谢大佬回复啊,我明白在c++ 中也可以设置全局函数,用面向过程的方式来编写。可是在此处,solve函数作为fvMatrix类的成员函数,真的可以 直接以 “函数名加实参”的方式调用吗?谢谢!



  • 看icoFoam.C的头文件fvCFD.H文件(~src/finiteVolume/cfdTools/general/include/),里边的fvMatrices.H头文件(~src/finiteVolume/fvMatrices/)就两行代码,留意到fvMatricesFwd.H头文件。

    39 #include "fvMatricesFwd.H"
    

    看到fvMatricesFwd.H文件(~src/finiteVolume/fvMatrices/)指出存在fvVectorMatrix是fvMatrix<vector>的别名。

    45 typedef fvMatrix<vector> fvVectorMatrix;
    

    找到fvMatrix.H头文件(~src/finiteVolume/fvMatrices/fvMatrix/),里边都是变量和函数,就顺便取看看fvMatrix.C文件的内容。

    在fvMatrix.C文件(~src/finiteVolume/fvMatrices/fvMatrix/)中意外找到了==的运算符重载,就是solve(UEqn == -fvc::grad(p));括号里边的运算符,A==B返回的是A-B。留意到最后一句告诉我有一个fvMatrixSolve.C文件。

    1356 template<class Type>
    1357 Foam::tmp<Foam::fvMatrix<Type>> Foam::operator==
    1358 (
    1359     const fvMatrix<Type>& A,
    1360     const fvMatrix<Type>& B
    1361 )
    1362 {
    1363     checkMethod(A, B, "==");
    1364    return (A - B);
    1365 }
    
    2336 // * * * * * * * * * * * * * * * * Solvers * * * * * * * * * * * * * * * * * //
    2337 
    2338 #include "fvMatrixSolve.C"
    

    于是,我在fvMatrixSolve.C文件(~src/finiteVolume/fvMatrices/fvMatrix/)中找到了下面这个函数:

    418 template<class Type>
    419 Foam::SolverPerformance<Type> Foam::solve(fvMatrix<Type>& fvm)
    420 {
    421     return fvm.solve();
    422 }
    

    这是什么啊?
    变量名作为实参的solve函数,返回的是变量名的成员函数。
    得证。



  • @wangfei9088 十分感谢,您追踪代码的执行力太强了。我也按照您的搜索路径走了一遍,发现果然如此。您最后最终到的 Foam::solve函数看来应该是个全局函数,并且由这个全局函数来调用fvMatrix中的成员函数solve.请问这么理解对吗?谢谢!
    另外您提到如下图所示的
    97edc7182f685fb10bac7878984c607.png
    编译没有问题,但是运行报错。我重复了您的步骤,发现确实如此,原因应该是这种变动并不是等价变动,因为更改了UEqn的值(此后UEqn作为单独整体出现并参与计算了)。所以我做了如下的等价变动
    a1891e7ded7f2b2443cbc3f1cfb6027.png
    讲道理这样应该可以获得正确结果,可以居然连编译都编译不过了。。。好奇怪啊:138: :138:
    aee8537299d0308e530a09c019c8264.png


  • 管理员

    应该用(Ueqn==fvc::grad(p)).ref()->solve(),这是一个tmp类型

    @wangfei9088 大佬太厉害了 :140:



  • @李东岳 芜湖!谢谢岳哥!



  • @李东岳 老师,我就一菜鸟,班门弄斧啦。最后一笔还得靠您这样的大佬来点睛啊。学习了! :xiezuoye:



  • @李东岳solve函数为啥不需要用对象去访问调用? 中说:

    应该用(Ueqn==fvc::grad(p)).ref()->solve(),这是一个tmp类型

    @wangfei9088 大佬太厉害了 :140:

    这里.ref() 是取引用吧,所以应该是

    (Ueqn==fvc::grad(p)).ref().solve() 或者

    (Ueqn==fvc::grad(p))->solve()

    @Micro 大佬试过李东岳老师修改后的代码了吗?



  • @Yongbo 还没有,我按照您说的试一下,你尝试后有结果了吗?



  • @Yongbo 你说的两种方式是对的,我验证均通过编译了。东岳老师应该是笔误了


Log in to reply
 


CFD中文网 | 东岳流体学术 | 东岳流体商业 | 吉ICP备20003622号-1