我是一名试图学习C ++的JAVA开发人员,但我真的不知道标准函数声明的最佳实践是什么。
在课堂上:
class Clazz
{
public:
void Fun1()
{
//do something
}
}
或在外面:
class Clazz
{
public:
void Fun1();
}
Clazz::Fun1(){
// Do something
}
我觉得第二个可能不太可读......
答案 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)
内联函数(每次在类中声明它们时的函数)每次调用时都会被粘贴到您的主内存代码中。当您在类之外声明函数时,调用函数时它来自同一内存。这就是为什么它要好得多的原因。