类内或类外的函数声明

发布于 2024-12-31 22:21:36 字数 284 浏览 2 评论 0原文

标准函数声明的最佳实践是什么。

在课堂上:

class Clazz
{
 public:
    void Fun1()
    {
        //do something
    }
}

或者在外面:

class Clazz
{
public:
    void Fun1();
}

Clazz::Fun1(){
    // Do something
}

我有一种感觉,第二个可能不太可读......

what the best practice is for standard function declarations.

In the class:

class Clazz
{
 public:
    void Fun1()
    {
        //do something
    }
}

Or outside:

class Clazz
{
public:
    void Fun1();
}

Clazz::Fun1(){
    // Do something
}

I have a feeling that the second one can be less readable...

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

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

发布评论

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

评论(8

我很OK 2025-01-07 22:21:36

C++ 是面向对象的,因为它支持软件开发的面向对象范例。

然而,与 Java 不同的是,C++ 并不强制您将函数定义分组到类中:声明函数的标准 C++ 方法是仅声明一个函数,而不包含任何类。

如果您正在谈论方法声明/定义,那么标准方法是将声明放入包含文件(通常命名为 .h.hpp)和定义中在单独的实现文件中(通常命名为 .cpp.cxx)。我同意这确实有点烦人并且需要一些重复,但这就是语言的设计方式(主要概念是 C++ 编译一次完成一个单元:您需要正在编译的单元的 .cpp 和只是 .h编译代码使用的所有单元;换句话说,类的包含文件必须包含能够生成使用该类的代码所需的所有信息)。有很多关于此的细节,对编译速度、执行速度、二进制大小和二进制兼容性有不同的影响。

对于快速实验来说,任何事情都有效......但对于更大的项目,分离实际上是必需的(并且它并不明确......将一些实现细节保留在公共.h中可能是有意义的)。

如果您正在寻找为什么需要进行这种拆分的逻辑解释,您将找不到。因为没有。编译器仍然可以仅使用一个文件的一次一个编译单元模型(仅考虑接口细节,即使实现位于同一文件中)。但这是 C++,所以你被迫进行拆分并重复两次而不犯错误(否则如果代码不起作用,那是你的错:编译器不需要检测 中内容之间的所有不兼容性.h 以及 .cpp 中的内容;有些会被检测到,有些则不会,如果您犯了这种错误,就会(可能)破坏您计算机上的所有数据)。
原因主要是“因为”(我自己的合理化可能是使编译器更简单,并且当时它被认为是一个重要的“功能”,能够发布 .h 文件并保持实现秘密)。

注意:即使您了解 Java,C++ 也是一种完全不同的语言……并且它是一种不能仅通过实验来学习的语言。原因是它是一种相当复杂的语言,有很多不对称性和明显不合逻辑的选择,最重要的是,当你犯错误时,没有像 Java 那样的“运行时错误天使”来拯救你……而是有“未定义的行为守护进程”。

学习 C++ 的唯一合理方法是阅读......无论你多么聪明,你都无法猜测委员会的决定(实际上,聪明有时甚至是一个问题,因为正确的答案是不合逻辑的,并且是历史的结果)遗产。)

只需挑选一两本好书,除了进行实验之外,还可以从头到尾地阅读它们。单独进行实验不会让您达到像样的 C++ 熟练程度。

C++ is object oriented, in the sense that it supports the object oriented paradigm for software development.

However, differently from Java, C++ doesn't force you to group function definitions in classes: the standard C++ way for declaring a function is to just declare a function, without any class.

If instead you are talking about method declaration/definition then the standard way is to put just the declaration in an include file (normally named .h or .hpp) and the definition in a separate implementation file (normally named .cpp or .cxx). I agree this is indeed somewhat annoying and requires some duplication but it's how the language was designed (the main concept is that C++ compilation is done one unit at a time: you need the .cpp of the unit being compiled and just the .h of all the units being used by the compiled code; in other words the include file for a class must contain all the information needed to be able to generate code that uses the class). There are a LOT of details about this, with different implications about compile speed, execution speed, binary size and binary compatibility.

For quick experiments anything works... but for bigger projects the separation is something that is practically required (and it's not clear cut... it may make sense to keep SOME implementation details in the public .h).

If you're looking for a logical explanation of why this split is necessary you won't find one. Because there's none. The compiler could still use the one-compilation-unit-at-a-time model with just one file (by considering only the interface details, even if the implementation is in the same file). But this is C++, so you're forced to do the split and repeat things twice without making mistakes (otherwise it's YOUR fault if the code doesn't work: compilers are not required to detect all incompatibilities between what is in the .h and what is in .cpp; some are detected and some are not and just will (possibly) destroy all data on your computer if you make that kind of mistake).
The reason is mostly "because" (my own rationalization is may be keeping the compiler simpler and that back then it was considered an important "feature" being able to publish .h files and keep implementations secret).

Note: Even if you know Java, C++ is a completely different language... and it's a language that cannot be learned just by experimenting. The reason is that it's a rather complex language with a lot of asymmetries and apparently illogical choices, and most importantly, when you make a mistake there are no "runtime error angels" to save you like in Java... but there are instead "undefined behavior daemons".

The only reasonable way to learn C++ is by reading... no matter how smart you are there is no way you can guess what the committee decided (actually being smart is sometimes even a problem because the correct answer is illogical and a consequence of historical heritage.)

Just pick a good book or two and read them cover to cover in addition to experimenting. Experimenting alone will take you nowhere near a decent level of C++ proficiency.

ˇ宁静的妩媚 2025-01-07 22:21:36

第一个将您的成员函数定义为内联函数 ,而第二个则没有。在这种情况下,函数的定义位于标头本身中。

第二种实现将函数的定义放在 cpp 文件中。

两者在语义上是不同的,这不仅仅是风格问题。

The first defines your member function as an inline function, while the second doesn't. The definition of the function in this case resides in the header itself.

The second implementation would place the definition of the function in the cpp file.

Both are semantically different and it is not just a matter of style.

美羊羊 2025-01-07 22:21:36

函数定义在类之外更好。这样您的代码就可以在需要时保持安全。头文件应该只给出声明。

假设有人想使用你的代码,你可以给他你的类的.h文件和.obj文件(编译后获得)。他不需要 .cpp 文件来使用您的代码。

这样您的实施对其他人来说是不可见的。

Function definition is better outside the class. That way your code can remain safe if required. The header file should just give declarations.

Suppose someone wants to use your code, you can just give him the .h file and the .obj file (obtained after compilation) of your class. He does not need the .cpp file to use your code.

That way your implementation is not visible to anyone else.

策马西风 2025-01-07 22:21:36

“类内”(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. 

The "Inside the class" (I) method does the same as the "outside the class" (O) method.

However, (I) can be used when a class is only used in one file (inside a .cpp file). (O) is used when it is in a header file. cpp files are always compiled. Header files are compiled when you use #include "header.h".

If you use (I) in a header file, the function (Fun1) will be declared every time you include #include "header.h". This can lead to declaring the same function multiple times. This is harder to compile, and can even lead to errors.

Example for correct usage:

File1: "Clazz.h"

//This file sets up the class with a prototype body. 

class Clazz
{
public:
    void Fun1();//This is a Fun1 Prototype. 
};

File2: "Clazz.cpp"

#include "Clazz.h" 
//this file gives Fun1() (prototyped in the header) a body once.

void Clazz::Fun1()
{
    //Do stuff...
}

File3: "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.

File4: "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. 

File5: "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. 
夜清冷一曲。 2025-01-07 22:21:36

成员函数可以在类定义中定义,也可以使用范围解析运算符 :: 单独定义。在类定义中定义成员函数会声明该函数为内联函数,即使您不使用内联说明符也是如此。因此,您可以如下定义 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)
,这两种方式都是合法的。

我不是专家,但我认为,如果您只将一个类定义放在一个文件中,那么这并不重要。

但是如果您应用内部类之类的东西,或者您有多个类定义,那么第二个类将难以阅读和维护。

Member functions can be defined within the class definition or separately using scope resolution operator, ::. Defining a member function within the class definition declares the function inline, even if you do not use the inline specifier. So either you can define Volume() function as below:

class Box
{
  public:

     double length;
     double breadth;    
     double height;     

     double getVolume(void)
     {
        return length * breadth * height;
     }
};

If you like you can define same function outside the class using scope resolution operator, :: as follows

double Box::getVolume(void)
{
   return length * breadth * height;
}

Here, only important point is that you would have to use class name just before :: operator. A member function will be called using a dot operator (.) on a object where it will manipulate data related to that object only as follows:

Box myBox;           

myBox.getVolume();  

(from: http://www.tutorialspoint.com/cplusplus/cpp_class_member_functions.htm)
, both ways are legal.

I'm not an expert, but I think, if you put only one class definition in one file, then it does not really matter.

but if you apply something like inner class, or you have multiple class definition, the second one would be hard to read and maintained.

夜清冷一曲。 2025-01-07 22:21:36

第一个必须放在头文件中(类的声明所在的位置)。第二个可以是任何地方,可以是标头,也可以是源文件。在实践中,您可以将小函数放在类声明中(这将它们隐式地声明为内联,尽管编译器最终决定它们是否内联)。但是,大多数函数在标头中都有声明,并在 cpp 文件中实现,就像第二个示例一样。不,我不认为有任何理由会降低可读性。更不用说您实际上可以将某个类型的实现拆分到多个 cpp 文件中。

The first one must be put in the header file (where the declaration of the class resides). The second can be anywhere, either the header or, usually, a source file. In practice you can put small functions in the class declaration (which declares them implicitly inline, though it's the compiler that ultimately decides whether they will be inlined or not). However, most functions have a declaration in the header and the implementation in a cpp file, like in your second example. And no, I don't see any reason why this would be less readable. Not to mention you could actually split the implementation for a type across several cpp files.

眼泪也成诗 2025-01-07 22:21:36

默认情况下,在类内部定义的函数被视为内联函数。
为什么应该在外部定义函数的一个简单原因是:

类的构造函数检查虚拟函数并初始化虚拟指针以指向正确的 VTABLE 或 虚方法表,调用基类构造函数,并初始化当前类的变量,所以实际上做了一些工作。

当函数不太复杂时使用内联函数,可以避免函数调用的开销。 (开销包括硬件级别的跳转和分支。)
并且如上所述,构造函数并不像内联那么简单。

A function that is defined inside a class is by default treated as an inline function.
A simple reason why you should define your function outside:

A constructor of the class checks for virtual functions and initializes a virtual pointer to point to the proper VTABLE or the virtual method table, calls the base class constructor, and initializes variables of the current class, so it actually does some work.

The inline functions are used when functions are not so complicated and avoids the overhead of the function call. (The overhead includes a jump and branch on the hardware level.)
And as described above, the constructor is not as simple to be considered as inline.

穿越时光隧道 2025-01-07 22:21:36

内联函数(当您在类中声明它们时的函数)每次调用它们时,它们都会粘贴到您的主内存代码中。当您在类外部声明该函数时,当您调用该函数时,它来自同一内存。这就是为什么它要好得多。

Inline functions(functions when you declare them in the class ) every time when call them they are pasted in your main memeory code. While when you declare the function outside the class, the when you call the fuction it comes from the same memory. Thats why it is much better.

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