C++ .cpp 文件中的内联成员函数

发布于 2024-09-28 16:43:00 字数 536 浏览 3 评论 0原文

我知道根据定义,内联成员函数应该进入标题。但是,如果无法将函数的实现放入标头中怎么办?让我们考虑这种情况:

File Ah

#pragma once
#include "B.h"

class A{
    B b;
};

File Bh

#pragma once

class A; //forward declaration

class B{
    inline A getA();
};

由于循环包含,我必须将 getA 的实现放入

B.cpp

#include "B.h"
#include "A.h"

inline A B::getA(){
    return A();
}

编译器会内联 getA 吗?如果是,那么哪个内联关键字是重要的(标头中的关键字或 .cpp 文件中的关键字)?是否有另一种方法将内联成员函数的定义放入其 .cpp 文件中?

I know that inline member functions by definition should go into the header. But what if it's not possible to put the implementation of the function into the header? Let's take this situation:

File A.h

#pragma once
#include "B.h"

class A{
    B b;
};

File B.h

#pragma once

class A; //forward declaration

class B{
    inline A getA();
};

Due to the circular include I have to put the implementation of getA into

B.cpp

#include "B.h"
#include "A.h"

inline A B::getA(){
    return A();
}

Will the compiler inline getA? If so, which inline keyword is the significant one (the one in the header or the one in the .cpp file)? Is there another way to put the definition of an inline member function into its .cpp file?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

手心的海 2024-10-05 16:43:00

引用自 C++ 常见问题解答

注意:必须
函数的定义(部分
在 {...}) 之间放置在
头文件,除非函数是
仅在单个 .cpp 文件中使用。在
特别是,如果你把内联
将函数的定义写入 .cpp 文件
然后你从其他 .cpp 中调用它
文件,你会得到一个“未解决的
来自链接器的外部”错误。

每当编译器发现内联函数的任何使用时,编译器都需要查看该内联函数的定义。如果内联函数放置在头文件中,则通常是可能的。

编译器会内联 getA 吗?

不可以,除非在 B.cpp 本身中使用 getA()

如果是,哪个内联关键字是重要的(标头中的关键字或 cpp 中的关键字)?

最佳实践:仅在定义之外类体。

是否有另一种方法可以将内联成员函数的定义放入其 cpp 文件中?

不,至少我不知道。

Quoting from C++ FAQ:

Note: It's imperative that the
function's definition (the part
between the {...}) be placed in a
header file, unless the function is
used only in a single .cpp file. In
particular, if you put the inline
function's definition into a .cpp file
and you call it from some other .cpp
file, you'll get an "unresolved
external" error from the linker.

The compiler need to see the definition of the inline function whenever it finds any use of that inline function. That is typically possible if the inline function is placed in a header file.

Will the compiler inline getA?

No, except when the the use of getA() is in B.cpp itself.

If so, which inline keyword is the significant one (the one in the header or the one in the cpp)?

Best practice: only in the definition outside the class body.

Is there another way to put the definition of an inline member function into it's cpp file?

No, at least I don't know.

十年九夏 2024-10-05 16:43:00

它不能在 B.cpp 的范围之外。编译器在每个编译单元的基础上运行,即它单独编译每个 .cpp 文件,因此如果它编译 C.cpp,它将没有可用的 getA() 代码,并且需要执行函数调用和让链接器修复它(或者,如果它确实按字面意思并尝试内联,最终会出现链接器错误。inlinestatic 具有相似的品质代码>)。

唯一的例外是 LTCG,即链接时代码生成,它可在较新的编译器上使用。

在这种情况下,一种方法是使用另一个包含内联代码的头文件(有时称为 *.inl 文件)。

编辑: 至于哪个内联相关 - 它是类定义中的内联,即头文件中的内联。请记住,许多编译器对于什么可以内联以及什么应该内联有自己的想法。例如,gcc 可以完全禁用内联(-O0),或者它可以内联任何它认为值得内联的内容(例如 -O3)。

It can't, outside the scope of B.cpp. The compiler operates on a per-compile-unit base, i.e. it compiles each .cpp file individually, so if it compiles C.cpp, it won't have the code for getA() available and will need to perform a function call and have the linker fix it up (or, if it really took you by the word and tried to inline, it will have end up with a linker error. inline has similar qualities as static).

The only exception is LTCG, i.e. link-time code generation, which is available on newer compilers.

One approach in this case is to have another header file (sometimes named *.inl files) that contain the inlined code.

EDIT: As for which inline is relevant - it's the one in the class definition, i.e. in the header file. Keep in mind that many compilers have their own mind on what can and should be inlined. gcc for example can disable inlining completely (-O0), or it can inline anything that it deems worth inlining (like -O3).

俯瞰星空 2024-10-05 16:43:00

我会从相反的方向来解决这个问题。

不要向函数添加内联声明(除非您也需要)。

唯一需要将内联声明添加到函数/方法的情况是,如果您在头文件中但在类声明之外定义了该函数。

Xh

class X
{
    public:
        int getX()   { return 4;} // No inline because it is part of the class.
                                  // The compiler knows that needs an inline tag
        int getY();
        int getZ();
};

inline
int X::getY()  { return 5;}       // This needs to be explicitly declared inline.
                                  // Otherwise the linker will complain about
                                  // multiple definitions in compilation units.

X.cpp

 // Never declare anything inline in the cpp file.

 int X::getZ() { return 6; }

给你更具体的案例。
删除所有内联规范。他们没有做你认为他们在做的事情。

I would go about this from the opposite direction.

Don't add inline declarations to your function (unless you need too).

The only time you need to add the inline declaration to a function/method is if you define the function in a header file but outside the class declaration.

X.h

class X
{
    public:
        int getX()   { return 4;} // No inline because it is part of the class.
                                  // The compiler knows that needs an inline tag
        int getY();
        int getZ();
};

inline
int X::getY()  { return 5;}       // This needs to be explicitly declared inline.
                                  // Otherwise the linker will complain about
                                  // multiple definitions in compilation units.

X.cpp

 // Never declare anything inline in the cpp file.

 int X::getZ() { return 6; }

To you more specific case.
Remove all the inline specifications. They are not doing what you think they are doing.

不念旧人 2024-10-05 16:43:00

如今,大多数编译器都可以在链接时以及编译时执行内联。如果您的函数可能受益于内联,那么链接时间优化器很可能会这样做。

当链接器到达它时,除了编译器会将某些对象标记为可收集之外,关于编译器输出的内联状态的信息并不多,例如,因为内联函数或类模板实例出现在多个编译单元中,或者当多个符号共享一个名称时,例如 main 函数被定义两次,它应该会引发错误。这些都不会影响它将生成的实际代码。

These days, most compilers can perform inlining at link time, as well as compile time. If your function is likely to benefit from inlining, then the Link Time optimizer is likely to do just that.

By the time the linker gets to it, not much about the inline status of compiler output is available, except that the compiler will flag certain objects as being collectible, for instance because an inline function or class template instance appears in multiple compilation units, or it should raise an error when multiple symbols share a name, such as the main function being defined twice. None of this has influence on the actual code it will generate.

天赋异禀 2024-10-05 16:43:00

这是我的做法。

File Ah

#pragma once
#include "B.h"

class A {
    B b;
};

File Bh

#pragma once

class B {
public:
    template<class T> inline T getA() {
        assert(NULL); // Use 'getA<A>()' template specialization only!
        return NULL;
    }
};

class A; // Forward declaration
template<> inline A B::getA<A>();

File Ch

#pragma once
#include "A.h"
#include "B.h"

// Implement template specialization here!
template<> inline A B::getA<A>() { return A(); }

只需包含“Ch”文件即可使用 getA() 方法。原始代码的唯一变化是 getA() 方法必须定义为公共方法而不是私有方法。

然而,正如你们许多人所解释的那样,这并不是真正有用。

Here is the way I did it.

File A.h

#pragma once
#include "B.h"

class A {
    B b;
};

File B.h

#pragma once

class B {
public:
    template<class T> inline T getA() {
        assert(NULL); // Use 'getA<A>()' template specialization only!
        return NULL;
    }
};

class A; // Forward declaration
template<> inline A B::getA<A>();

File C.h

#pragma once
#include "A.h"
#include "B.h"

// Implement template specialization here!
template<> inline A B::getA<A>() { return A(); }

Just include the "C.h" file to be able to use getA() method. The only change with the original code is that the getA() method must be defined as public instead of private.

However, as many of you explained it, this is not really useful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文