类内外的函数声明

时间:2012-01-31 07:30:21

标签: c++ inline

我是一名试图学习C ++的JAVA开发人员,但我真的不知道标准函数声明的最佳实践是什么。

在课堂上:

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

或在外面:

class Clazz
{
public:
    void Fun1();
}

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

我觉得第二个可能不太可读......

8 个答案:

答案 0 :(得分:45)

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

然而,与Java不同,C ++并不强制您在类中对函数定义进行分组:声明函数的标准C ++方法是仅声明一个函数,而不需要任何类。

如果您正在谈论方法声明/定义,那么标准方法是将声明仅放在包含文件(通常名为.h.hpp)中,并将定义放在单独的实现文件中(通常命名为.cpp.cxx)。我同意这确实有些烦人,需要一些重复,但这就是语言的设计方式。

对于快速实验和单个文件项目,任何事情都可行......但对于更大的项目,这种分离是实际需要的。

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

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

只需选择一个good book或两个,然后阅读封面即可。

答案 1 :(得分:19)

第一个将您的会员功能定义为 inline function ,而第二个则不是。在这种情况下,函数的定义位于标题本身。

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

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

答案 2 :(得分:15)

在课堂外,函数定义更好。这样,如果需要,您的代码可以保持安全。头文件应该只提供声明。

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

这样,任何人都无法看到您的实施。

答案 3 :(得分:10)

“在课堂内部”(I)方法与“课外”(O)方法相同。

但是,当一个类仅用于一个文件(在.cpp文件中)时,可以使用(I)。 (O)在头文件中使用。 cpp文件总是被编译。使用#include“header.h”编译头文件。

如果在头文件中使用(I),则每次包含#include“header.h”时都会声明函数(Fun1)。这可能导致多次声明相同的功能。这很难编译,甚至可能导致错误。

正确使用的示例:

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. 

答案 4 :(得分:3)

成员函数可以在类定义中定义,也可以使用作用域解析运算符::。即使不使用内联说明符,在类定义中定义成员函数也会声明函数内联。因此,您可以定义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;
}

这里,唯一重要的一点是你必须在:: operator之前使用类名。将在对象上使用点运算符(。)调用成员函数,它将仅操作与该对象相关的数据,如下所示:

Box myBox;           

myBox.getVolume();  

(来自:http://www.tutorialspoint.com/cplusplus/cpp_class_member_functions.htm) 两种方式都是合法的。

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

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

答案 5 :(得分:2)

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

答案 6 :(得分:1)

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

该类的构造函数检查虚函数并初始化虚拟指针以指向正确的VTABLE或virtual method table,调用基类构造函数,并初始化当前类的变量,因此它实际上做了一些工作

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

答案 7 :(得分:0)

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