C++:成员和非成员函数之间的区别
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5920916/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
c++: Difference between member and non member functions
提问by Luke
What is the difference between member and non-member functions in C++?
C++中的成员函数和非成员函数有什么区别?
回答by Matthieu M.
There are several differences between a member function (which I will now call method) and a free function (which I will now call function).
成员函数(我现在将调用method)和自由函数(我现在将调用function)之间有几个区别。
First, let's just state that they are not sodifferent. Object code can generally be compiled down to C (or assembly) which are procedural languages with no notion of methods. Both methods and functions are then calledlike subroutines.
首先,让我们声明它们并没有太大的不同。目标代码通常可以编译成 C(或汇编),它们是没有方法概念的过程语言。那么这两种方法和功能都被称为像子程序。
Now that this is out of the way, let's look at the differences. They can be classified in two categories: conceptual and syntactic.
既然这已经解决了,让我们看看差异。它们可以分为两类:概念性的和句法的。
Syntactically
句法上
The syntax is the obvious part of any language, so it's the easiest to get out of the way.
语法是任何语言的明显部分,因此最容易避开。
First note: there are two different kinds of methods in C++ (and a number of other languages), the static
methods and regular methods.
首先注意:C++(和许多其他语言)中有两种不同的方法,static
方法和常规方法。
Both kinds of methods have full access to the class internals (protected
and private
sections) as well (of course) as access to the class public
interface.
这两种方法都可以完全访问类内部(protected
和private
部分)以及(当然)访问类public
接口。
static
methods are equivalent to friend
functions (apart from some scoping differences).
static
方法等价于friend
函数(除了一些作用域差异)。
Within a regular method, a special keyword (this
in C++) allows access to the current object on which the method has been invoked (via the .
, ->
, .*
or ->*
operators).
内一个普通的方法,一个特殊的关键字(this
在C ++)允许访问其上的方法已被调用当前对象(通过.
,->
,.*
或->*
操作员)。
A regular method may be const
and/or volatile
qualified, enabling it for (respectively) const
and/or volatile
qualified objects. For example, a non-const
method cannot be called on a const
object. This can be seen as qualifying this
within the method, ie void Foo::bar() const
has a this
of type Foo const*
.
常规方法可以是const
和/或volatile
限定的,为(分别)const
和/或volatile
限定的对象启用它。例如,const
不能在const
对象上调用非方法。这可以看作是this
方法内的限定,即void Foo::bar() const
具有this
类型为Foo const*
。
A regular method may be marked as virtual
. Virtuality enables runtime polymorphism by enabling overriding. I won't extend on this mechanism here, let's just note that functions cannot be virtual.
常规方法可以标记为virtual
。虚拟性通过启用覆盖来实现运行时多态性。我不会在这里扩展这个机制,让我们注意函数不能是虚拟的。
One often ignored point, is that methods (both static
and regular) are scoped within the class. This is important for name lookup (of other methods or attributes/variables) as it means that the elements of the class have priority during lookup from a method on the elements declared outside of the class.
一个经常被忽视的一点是,方法(包括static
常规方法)都在类内。这对于名称查找(其他方法或属性/变量的)很重要,因为这意味着在从类外部声明的元素上的方法查找期间,类的元素具有优先级。
Since the qualification using this->
before attribute or methods is not mandatory, this comes handy in regular methods, though it may introduce subtle bugs. In static methods, it avoids qualifying by the class name the static attributes and methods one whishes to access.
由于使用this->
before 属性或方法的限定不是强制性的,这在常规方法中很方便,尽管它可能会引入细微的错误。在静态方法中,它避免通过类名限定想要访问的静态属性和方法。
Now that the main syntactic differences have been asserted, let's check the conceptual differences.
现在已经断言了主要的句法差异,让我们检查一下概念上的差异。
Conceptually
概念上
OOP is generally about tying together state and behavior (of this state). This is done by creating classes which group attributes (state) and behavior (methods) and (in theory) stating that only the methods can act on the state. Therefore, in OOP, the methods are responsible for implementing the behavior of the class.
OOP 通常是将状态和行为(该状态的)联系在一起。这是通过创建对属性(状态)和行为(方法)进行分组并且(理论上)声明只有方法可以作用于状态的类来完成的。因此,在 OOP 中,方法负责实现类的行为。
The methods participate to the encapsulation of state (freeing clients from the implementation detail) and to the preservation of the class invariants (statements about the class state that hold true from its birth to its death, whatever you do with it).
这些方法参与状态的封装(将客户从实现细节中解放出来)和类不变量的保存(关于类状态的声明,从它的诞生到它的死亡,无论你用它做什么)。
C++
C++
In C++, as we have seen previously, this is done by using different access levels (public
, protected
and private
) and granting access to the non-public
levels to a restricted portion of the code. Generally attributes will be private and thus only accessible to the class methods (and maybe some friends, for syntax quirks).
在 C++ 中,正如我们之前看到的,这是通过使用不同的访问级别(public
,protected
和private
)并将非public
级别的访问权限授予代码的受限部分来完成的。通常属性是私有的,因此只能被类方法访问(可能还有一些朋友,因为语法怪癖)。
Note: I urge you not to use protected
attributes, it's hard to track down their modifications and since the set of derived classes is unbounded... their implementation cannot be changed easily afterward.
注意:我劝你不要使用protected
属性,很难追踪它们的修改,而且由于派生类的集合是无界的......之后它们的实现不能轻易改变。
However, beware that C++ discourages from bloating the interface with lots of methods.
但是,请注意 C++ 不鼓励使用大量方法使接口膨胀。
The trouble is that because methods are responsible of maintaining invariants, the more there are and the more the responsability is spread, making it more difficult to track down bugs and ensure correctness. Also, since methods depends on the class internals, it makes change more costly.
问题在于,因为方法负责维护不变量,所以不变量越多,责任分散的越多,因此更难追踪错误并确保正确性。此外,由于方法取决于类的内部结构,因此更改成本更高。
Instead, in C++, it is generally advised to write a minimal set of methods and delegating the rest of the behavior to non-friend
functions (as long as it doesn't increase the cost too much).
相反,在 C++ 中,通常建议编写最少的方法集并将其余行为委托给非friend
函数(只要它不会增加太多成本)。
- See Sutter's take on
std::string
in Monolith Unstrung. - The delegation to non-friend methods was emphasized by Sutter in its Interface Principlein which he states that functions that are delivered with the class (in the same file/same namespace) and use the class, are logically part of the class interface. He restates in Exceptional C++.
- 参见 Sutter
std::string
在Monolith Unstrung 中的看法。 - Sutter 在其接口原则中强调了对非友元方法的委托,他指出与类一起交付(在同一文件/同一命名空间中)并使用该类的函数在逻辑上是类接口的一部分。他在 Exceptional C++ 中重申。
This answer is becoming rather long-winded, yet I suspect that I have overlooked differences that other would find critical... oh well.
这个答案变得相当冗长,但我怀疑我忽略了其他人认为至关重要的差异……哦,好吧。
回答by Marc Mutz - mmutz
A (non-static) member functionhas an implicit this
argument, a non-member doesn't.
(非静态)成员函数有一个隐式this
参数,非成员没有。
Syntactically, you pass that implicit argument on the left of the .
or ->
operator like.so()
or like->so()
, instead of as a function argument so( like )
.
从语法上讲,您在.
or->
运算符like.so()
or的左侧传递该隐式参数like->so()
,而不是作为函数参数so( like )
。
Likewise, when declaring a member function, you need to do so in the class of which it is a member:
同样,在声明成员函数时,您需要在它所属的类中这样做:
class Class {
public:
void a_public_member_function();
};
Non-member functions are instead declared outside any class (C++ calls this "at namespace scope").
非成员函数改为在任何类之外声明(C++ 称之为“在命名空间范围内”)。
(Non-static) member functions can also be virtual, but non-member functions (and static member functions) cannot.
(非静态)成员函数也可以是virtual,但非成员函数(和静态成员函数)不能。
回答by Alexander Gessler
A non-static
member function is invoked on objects of the class it belongs to. It has implicitly access to the this
pointer representing the current object. Through this pointer, it may access other members easily and with full access privileges (i.e. access private
members).
static
在它所属类的对象上调用非成员函数。它隐式地访问this
表示当前对象的指针。通过这个指针,它可以轻松地访问其他成员,并具有完全访问权限(即访问private
成员)。
A non-member function has no implicit this
. In the sample below, bar
is a member function while freebar
is not. Both do more or less the same, but note how bar
gets an implicit object pointer via this
(also only bar
has privileged access to foo
's members, freebar
only has access to public members).
非成员函数没有隐式this
. 在下面的示例中,bar
是成员函数,而freebar
不是。两者的作用或多或少相同,但请注意如何bar
通过this
(也只有bar
特权访问foo
的成员,freebar
只能访问公共成员)获取隐式对象指针。
class foo {
public:
void bar() {
this->x = 0; // equivalent to x = 0;
}
int x;
};
void freebar(foo* thefoo) {
thefoo->x = 1;
}
// ...
foo f;
f.bar();
// f.x is now 0
freebar(&f);
// f.x is now 1
Semantically a member function is more than just a function with an implicit this parameter. It is meant to define the behaviourof an object (i.e. a car object would have drive()
, stop()
as member functions).
从语义上讲,成员函数不仅仅是带有隐式 this 参数的函数。它旨在定义对象的行为(即汽车对象将具有drive()
,stop()
作为成员函数)。
Note that there are also static
member functions which have full privileges but don't get an implicit this
nor are they invoked through an instance of the class (but rather through the full name of the class).
请注意,还有一些static
成员函数具有完全权限,但不会获得隐式权限,也不会this
通过类的实例(而是通过类的全名)调用它们。
回答by Nawaz
In the following code, f()
is a member function of class Sample
, and g()
is a non-member function:
在下面的代码,f()
是类的一个成员函数Sample
,并且g()
是一种非成员函数:
class Sample
{
void f();
};
void g();
Its very simple. Since f()
is a member of the class Sample
, so its called member function (of class Sample
). And since g()
is not member of any class, so its called non-member function.
它非常简单。由于f()
是类的成员Sample
,所以它被称为(类的Sample
)成员函数。由于g()
不是任何类的成员,所以它被称为非成员函数。
回答by fredoverflow
A member function is invoked on an object and has access to the fields of the class.
成员函数在对象上被调用并且可以访问类的字段。
Member functions can be polymorphic (via the virtual
keyword) which is essential for OOP.
成员函数可以是多态的(通过virtual
关键字),这对于 OOP 是必不可少的。
回答by nobody
Member functions get called on instances and have a this
pointer available; non-members don't.
成员函数在实例上被调用并有一个this
可用的指针;非会员不会。