类内部或外部的函数声明
Function declaration inside or outside the class
我是一名JAVA开发人员,正在努力学习C++,但我真的不知道标准函数声明的最佳实践是什么。
在课堂上:
class Clazz
{
public:
void Fun1()
{
//do something
}
}
或外部:
class Clazz
{
public:
void Fun1();
}
Clazz::Fun1(){
// Do something
}
我有一种感觉,第二个可能不太可读。。。
C++是面向对象的,它支持软件开发的面向对象范式。
然而,与Java不同的是,C++并不强制您在类中对函数定义进行分组:声明函数的标准C++方法是只声明一个函数,而不声明任何类。
如果您讨论的是方法声明/定义,那么标准方法是将声明放在包含文件(通常命名为.h
或.hpp
)中,将定义放在单独的实现文件(通常名称为.cpp
或.cxx
)中。我同意这确实有点烦人,需要一些重复,但这就是语言的设计方式(主要概念是C++编译一次只完成一个单元:您需要被编译单元的.cpp,而只需要被编译代码使用的所有单元的.h;换句话说,类的include文件必须包含生成使用该类的代码所需的所有信息)。关于这一点有很多细节,包括编译速度、执行速度、二进制大小和二进制兼容性。
对于快速实验来说,任何东西都有效。。。但对于更大的项目来说,分离是实际需要的(即使公开一些实现细节可能是有意义的。h)。
注意:即使你知道Java,C++也是一种完全不同的语言。。。这是一种无法通过实验来学习的语言。原因是这是一种相当复杂的语言,有很多不对称和明显不合逻辑的选择,最重要的是,当你犯了一个错误时;运行时错误天使";像在Java中一样保存您。。。但取而代之的是";未定义的行为守护程序";。
学习C++的唯一合理方法是阅读。。。无论你有多聪明,你都无法猜测委员会的决定(实际上,聪明有时甚至是一个问题,因为正确的答案是不合逻辑的,是历史遗产的结果。)
只要挑选一两本好书,把它们从头到尾读一遍就行了。
第一个将成员函数定义为内联函数,而第二个则不定义。在这种情况下,函数的定义位于标头本身。
第二个实现将把函数的定义放在cpp文件中。
两者在语义上都不同,这不仅仅是风格的问题。
函数定义在类外更好。这样,如果需要,您的代码可以保持安全。头文件应该只给出声明。
假设有人想使用你的代码,你可以给他你类的.h文件和.obj文件(编译后获得)。他不需要.cpp文件来使用您的代码。
这样一来,其他人就看不到您的实现。
"类内"(I)方法与"类外"(O)方法相同。
但是,当一个类只在一个文件(.cpp文件内部)中使用时,可以使用(I)。(O) 在头文件中时使用。始终编译cpp文件。使用#include"Header.h"时会编译头文件。
如果在头文件中使用(I),则每次包含#include"header.h"时都会声明函数(Fun1)。这可能导致多次声明同一函数。这更难编译,甚至可能导致错误。
正确用法示例:
文件1:"Clazz.h"
//This file sets up the class with a prototype body.
class Clazz
{
public:
void Fun1();//This is a Fun1 Prototype.
};
文件2:"Clazz.cpp"
#include "Clazz.h"
//this file gives Fun1() (prototyped in the header) a body once.
void Clazz::Fun1()
{
//Do stuff...
}
文件3:"UseClazz.cpp"
#include "Clazz.h"
//This file uses Fun1() but does not care where Fun1 was given a body.
class MyClazz;
MyClazz.Fun1();//This does Fun1, as prototyped in the header.
文件4:"AlsoUseClazz.cpp"
#include "Clazz.h"
//This file uses Fun1() but does not care where Fun1 was given a body.
class MyClazz2;
MyClazz2.Fun1();//This does Fun1, as prototyped in the header.
文件5:"DoNotUseClazzHeader.cpp"
//here we do not include Clazz.h. So this is another scope.
class Clazz
{
public:
void Fun1()
{
//Do something else...
}
};
class MyClazz; //this is a totally different thing.
MyClazz.Fun1(); //this does something else.
成员函数可以在类定义中定义,也可以使用范围解析运算符:单独定义。在类定义中定义成员函数会以内联方式声明函数,即使不使用内联说明符也是如此。因此,您可以定义Volume()函数如下:
class Box
{
public:
double length;
double breadth;
double height;
double getVolume(void)
{
return length * breadth * height;
}
};
如果您喜欢,您可以使用范围解析操作符在类外定义相同的函数,:如下
double Box::getVolume(void)
{
return length * breadth * height;
}
这里,唯一重要的一点是,您必须在::操作符之前使用类名。成员函数将使用对象上的点运算符(.)调用,它将仅按如下方式处理与该对象相关的数据:
Box myBox;
myBox.getVolume();
(发件人:http://www.tutorialspoint.com/cplusplus/cpp_class_member_functions.htm),这两种方式都是合法的。
我不是专家,但我认为,如果在一个文件中只放一个类定义,那么这其实并不重要。
但是,如果您应用了类似内部类的东西,或者您有多个类定义,那么第二个类定义将很难阅读和维护。
第一个必须放在头文件中(类声明所在的位置)。第二个可以是任何位置,可以是头文件,也可以是源文件。在实践中,您可以将小函数放在类声明中(它隐式地内联声明它们,尽管最终决定它们是否内联的是编译器)。但是,大多数函数在头中都有声明,在cpp文件中有实现,就像第二个例子中一样。不,我看不出这本书可读性会降低的原因。更不用说,您实际上可以将一个类型的实现拆分到多个cpp文件中。
在类中定义的函数默认情况下被视为内联函数。您应该在外部定义功能的一个简单原因是:
该类的构造函数检查虚拟函数并初始化一个虚拟指针以指向正确的VTABLE或虚拟方法表,调用基类构造函数并初始化当前类的变量,因此它实际上做了一些工作。
内联函数是在函数不那么复杂的情况下使用的,可以避免函数调用的开销。(开销包括硬件级别的跳转和分支。)如上所述,构造函数并不像内联那样简单。
每次调用内联函数时,它们都会粘贴在主模因代码中。当你在类外声明函数时,当你调用函数时,它来自同一个内存。这就是为什么它好多了。
- Visual Studio中的函数声明和函数定义问题
- 为什么函数声明中允许 const?
- 如果 x.h 仅由函数声明组成,为什么有必要在 x 中包含 x.h.cpp
- * 和 ** 在 C++ 函数声明中是什么意思?
- 构造函数/函数声明参数列表中的统一初始化
- 在将函数声明为友元时,尖括号的含义是什么?
- 为什么转换函数声明不需要至少一个定义类型说明符
- 如何正确编写指针函数声明?
- 在"template"和函数声明之间使用:template<typename trait> using tr = base_trait<trait> void fn(tr::t
- 为什么要将函数声明和定义放在单独的文件中
- 为什么系统日志有两个不同的函数声明?
- 我如何获取数组的大小,以便我可以从函数声明所述数组
- 使用 enable_if 在按值传递与按引用传递之间更改函数声明
- JavaScript 中的一等函数和 C++ 中的函数声明
- C++ 通过函数声明后初始化向量
- VS2017 #error: : snprintf 的宏定义与标准库函数声明冲突
- C++ 17 个友元函数声明和内联命名空间
- MSVC 2017 - 错误 - 如何将模板类 X 的模板成员函数声明为嵌套类 X::Y 的好友
- 将派生类的构造函数声明为父类的友元
- 用于从 ANSI 字符串转换为 std::basic_string <TCHAR>的正确函数声明