我知道我的类方法有三种不同的实现“位置”:
1)在我的类(.h文件)中定义方法并在我的.cpp文件中实现它
//.h
class Foo
{
int getVal() const;
};
//.cpp
int Foo::getVal() const
{ return 0; }
2)在我的类(.h文件)中定义并实现该方法。
//.h
class Foo
{
int getVal() const
{ return 0; }
};
3)在我的类中定义方法并在类外但在我的头文件中实现它。
//.h
class Foo
{
int getVal() const;
};
int Foo::getVal() const
{ return 0; }
这三种方法有哪些主要区别?
这个问题有三个要素:可读性(代码看起来有多好),编译(编译器可以优化它多少)和实现隐藏(如果你使用代码作为库,你可能不想明确地分享你的特殊酱和世界一起)。
方法一只公开头文件中函数的接口。这意味着您将显示一个漂亮的干净界面,并且您的实现不会以纯文本形式公开。但是,代码不能跨编译单元内联,因此它有可能在运行时稍慢(实际上,这仅对非常非常非常小的代码百分比很重要)。这应该是你的默认方式。
方法2是隐式内联。冗长的功能会让你的课程变得混乱,因为(imho)很糟糕。还将您的实现暴露给全世界。但是,该函数可以内联,并且比在另一个地方定义它更简洁。我保留这个非常小的功能。
方法3实际上是非法的,因为你将打破一个定义规则,但以下是好的:
//Foo.h
class Foo {
int getVal() const;
};
inline int Foo::getVal() const {
return 0;
}
当我想保持类定义干净但想要头文件中的函数定义(对于inlinable或模板函数)时,我使用它。
(1)将为一个大型项目编译得更快(只需要编译定义 getVal
一旦进入Foo.cpp,只需要重新编译一件事,如果定义发生变化),你就可以为想要查找它的人获得一个非常清晰的类。另一方面,你不能内联 getVal()
。
(2)和(3)将编译得更慢,并为您的定义更改添加更多依赖项。但你可以内联 getVal()
。如果这是必需的 getVal
是一个模板功能。 注意 (3)如果多次包含标题会导致链接器错误 - 你必须记住记住标记你的功能 inline
。这是偏好(1)和(2)至(3)的一个很好的理由。
真的,这不是挑选(1)vs(2)的问题。您可能会在大型项目中使用它们 - 将标题中应该内联的函数的定义(和模板)放在标题中,并将内联中的内容放在cpp中。
在我开始之前的一个小注释,有很多单词用来描述这些东西非常相似,我将使用头文件中的部分声明(int getVal() const
)和cpp文件中部分的实现(int Foo::getVal() const
)。如果这些不完全准确,请道歉。
另请注意,在不明确的情况下,福利是对其他人的处罚。
1)在我的类(.h文件)中定义方法并在我的.cpp文件中实现它
这被认为是标准方法,并且通常被认为是默认方法(有许多例外,因此默认可能有点强)。
它将声明与实现分开。这提供了一些好处:
- 您只需要编译一次实现。这可能会节省编译时间。
- 您只需要参考声明。这可以避免排序问题,对于类之间的循环引用至关重要。
- 您不会分发您的实现,这对于闭源系统很有用,因为您经常需要分发大量的.h文件,以便其他人插入您的系统。
2)在我的类(.h文件)中定义并实现该方法。
这称为内联实现,它应该仅用于简单实现。它也有一些好处:
- 大多数编译器都将此视为一个巨大的内联提示。它不保证inling但很可能,对于简单的方法来说,这可能是一个胜利。属性样式方法是一个常见的例子。
- 你的实现很容易找到,因为它在声明中是直截了当的。
3)在我的类中定义方法并在类外但在我的头文件中实现它。
我以前没有见过这个,但是假设它在定义不重要时使用但你想要2的内联优点。 IdeaHat 提到了 inline
在这种情况下需要关键字。