c ++中的成员函数和非函数函数有什么区别。
答案 0 :(得分:24)
成员函数(我现在称之为 method )和自由函数(我现在称之为 function )之间存在一些差异。
首先,让我们说明他们不是所以不同。对象代码通常可以编译成C(或程序集),这是程序语言,没有方法概念。然后,这两个方法和函数都被称为,就像子程序一样。
现在已经不在了,让我们来看看差异。它们可以分为两类:概念和句法。
<强>在语法强>
语法是任何语言中显而易见的一部分,所以它最容易摆脱。
首先要注意:C ++(以及许多其他语言)有两种不同的方法,static
方法和常规方法。
这两种方法都可以完全访问类内部(protected
和private
部分),当然也可以访问类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 ++中,正如我们之前所见,这是通过使用不同的访问级别(static
,this->
和public
)并授予对非{{1}的访问权限来完成的。 }级别到代码的受限部分。通常属性是私有的,因此只能通过类方法访问(也可能是某些朋友,因为语法怪癖)。
注意:我建议你不要使用protected
属性,很难找到他们的修改,因为派生类的集合是无限的......之后不能轻易改变它们的实现。
但是,请注意C ++不鼓励使用大量方法使接口膨胀。
问题在于,因为方法负责维护不变量,所以存在的越多,责任的传播越多,使得追踪错误和确保正确性变得更加困难。此外,由于方法取决于类内部,因此更改成本更高。
相反,在C ++中,通常建议编写一组最小的方法,并将其余的行为委托给非private
函数(只要它不会增加太多的成本)。
public
的看法。这个答案变得相当冗长,但我怀疑我忽略了其他人会发现批评的差异......哦。好吧。
答案 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
指针可用;非会员不会。