c ++:成员函数和非成员函数之间的区别

时间:2011-05-07 12:09:41

标签: c++ oop

c ++中的成员函数和非函数函数有什么区别。

6 个答案:

答案 0 :(得分:24)

成员函数(我现在称之为 method )和自由函数(我现在称之为 function )之间存在一些差异。

首先,让我们说明他们不是所以不同。对象代码通常可以编译成C(或程序集),这是程序语言,没有方法概念。然后,这两个方法和函数都被称为,就像子程序一样。

现在已经不在了,让我们来看看差异。它们可以分为两类:概念和句法。

<强>在语法

语法是任何语言中显而易见的一部分,所以它最容易摆脱。

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

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

static方法等同于friend函数(除了一些范围差异)。

在常规方法中,特殊关键字(C ++中的this)允许访问调用该方法的当前对象(通过.->,{{ 1}}或.*运算符)。

常规方法可以->*和/或const限定,为(分别)volatile和/或const限定对象启用它。例如,无法在volatile对象上调用非const方法。这可以视为方法中的const符合条件,即this的{​​{1}}类型为void Foo::bar() const

常规方法可能会标记为this。 Virtuality通过启用覆盖来启用运行时多态性。我不会在这里扩展这个机制,让我们注意函数不能是虚拟的。

一个经常被忽略的一点是,方法(Foo const*和常规)都是在类中确定的。这对于名称查找(其他方法或属性/变量)很重要,因为这意味着在从类外部声明的元素的方法查找时,类的元素具有优先级。

由于在属性或方法之前使用virtual的限定不是强制性的,因此这在常规方法中很方便,但它可能会引入细微的错误。在静态方法中,它避免了通过类名限定静态属性和方法,以便访问。

现在主要的句法差异已被断言,让我们检查一下概念差异。

<强>概念

OOP通常将状态和行为(该状态)联系在一起。这是通过创建对属性(状态)和行为(方法)进行分组的类以及(理论上)声明只有方法可以对状态起作用来完成的。因此,在OOP中,方法负责实现类的行为。

这些方法参与了状态的封装(将客户从实现细节中解放出来)和类不变量的保存(关于从出生到死亡的类状态的陈述,无论你用它做什么)。

<强> C ++

在C ++中,正如我们之前所见,这是通过使用不同的访问级别(staticthis->public)并授予对非{{1}的访问权限来完成的。 }级别到代码的受限部分。通常属性是私有的,因此只能通过类方法访问(也可能是某些朋友,因为语法怪癖)。

注意:我建议你不要使用protected属性,很难找到他们的修改,因为派生类的集合是无限的......之后不能轻易改变它们的实现。

但是,请注意C ++不鼓励使用大量方法使接口膨胀。

问题在于,因为方法负责维护不变量,所以存在的越多,责任的传播越多,使得追踪错误和确保正确性变得更加困难。此外,由于方法取决于类内部,因此更改成本更高。

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

  • 请参阅Sutter对Monolith Unstrungpublic的看法。
  • Sutter在其Interface Principle中强调了对非朋友方法的委派,其中他声明与类一起提供的函数(在相同的文件/相同的命名空间中)并使用该类,在逻辑上是类接口。他在Exceptional C ++中重申。

这个答案变得相当冗长,但我怀疑我忽略了其他人会发现批评的差异......哦。好吧。

答案 1 :(得分:17)

(非静态)成员函数具有隐式this参数,非成员函数不具有。{/ p>

在语法上,您在.->运算符like.so()like->so()的左侧传递该隐式参数,而不是函数参数so( like )

同样,在声明成员函数时,您需要在其所属的类中执行此操作:

class Class {
public:
    void a_public_member_function();
};

非成员函数在任何类之外声明(C ++在命名空间范围内调用它)。

(非静态)成员函数也可以是虚拟,但非成员函数(和静态成员函数)不能。

答案 2 :(得分:8)

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

非成员函数没有隐式this。在下面的示例中,bar是成员函数,而freebar则不是。两者都或多或少相同,但请注意bar如何通过this获取隐式对象指针(也只有bar具有foo成员的特权访问权限{{ 1}}只能访问公共成员。)

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 drive()作为成员函数)。

请注意,还有stop()成员函数具有完全权限但不获取隐式static,也不通过类的实例调用它们(而是通过完整名称调用类)。

答案 3 :(得分:5)

在以下代码中,f()是类Sample的成员函数,g()是非成员函数:

class Sample
{
  void f();
};

void g();

非常简单。由于f()是类Sample的成员,因此其被称为成员函数(类Sample)。由于g()不是任何类的成员,因此它被称为非成员函数。

答案 4 :(得分:3)

在对象上调用成员函数,并且可以访问该类的字段。

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

答案 5 :(得分:1)

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