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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 19:11:39  来源:igfitidea点击:

c++: Difference between member and non member functions

c++oop

提问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 staticmethods and regular methods.

首先注意:C++(和许多其他语言)中有两种不同的方法,static方法和常规方法。

Both kinds of methods have full access to the class internals (protectedand privatesections) as well (of course) as access to the class publicinterface.

这两种方法都可以完全访问类内部(protectedprivate部分)以及(当然)访问类public接口。

staticmethods are equivalent to friendfunctions (apart from some scoping differences).

static方法等价于friend函数(除了一些作用域差异)。

Within a regular method, a special keyword (thisin 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 constand/or volatilequalified, enabling it for (respectively) constand/or volatilequalified objects. For example, a non-constmethod cannot be called on a constobject. This can be seen as qualifying thiswithin the method, ie void Foo::bar() consthas a thisof 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 staticand 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, protectedand private) and granting access to the non-publiclevels 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,protectedprivate)并将非public级别的访问权限授予代码的受限部分来完成的。通常属性是私有的,因此只能被类方法访问(可能还有一些朋友,因为语法怪癖)。

Note: I urge you not to use protectedattributes, 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-friendfunctions (as long as it doesn't increase the cost too much).

相反,在 C++ 中,通常建议编写最少的方法集并将其余行为委托给非friend函数(只要它不会增加太多成本)。

  • See Sutter's take on std::stringin 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++.
  • 参见 Sutterstd::stringMonolith 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 thisargument, 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-staticmember function is invoked on objects of the class it belongs to. It has implicitly access to the thispointer representing the current object. Through this pointer, it may access other members easily and with full access privileges (i.e. access privatemembers).

static在它所属类的对象上调用非成员函数。它隐式地访问this表示当前对象的指针。通过这个指针,它可以轻松地访问其他成员,并具有完全访问权限(即访问private成员)。

A non-member function has no implicit this. In the sample below, baris a member function while freebaris not. Both do more or less the same, but note how bargets an implicit object pointer via this(also only barhas privileged access to foo's members, freebaronly 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 staticmember functions which have full privileges but don't get an implicit thisnor 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 virtualkeyword) which is essential for OOP.

成员函数可以是多态的(通过virtual关键字),这对于 OOP 是必不可少的。

回答by nobody

Member functions get called on instances and have a thispointer available; non-members don't.

成员函数在实例上被调用并有一个this可用的指针;非会员不会。