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

Luk*_*uke 33 c++ oop

c ++中member和nonnember函数有什么区别.

Mat*_* M. 26

成员函数(我现在称之为方法)和自由函数(我现在称之为函数)之间存在一些差异.

首先,让我们说它们并没有那么不同.对象代码通常可以编译成C(或程序集),这是程序语言,没有方法概念.然后将这两个方法和函数称为子例程.

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

句法

语法是任何语言的明显部分,因此最简单的方法就是放弃.

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

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

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

内一个普通的方法,一个特殊的关键字(this在C++)允许访问其上的方法已被调用当前对象(通过.,->,.*->*操作员).

常规方法可以是const和/或volatile合格的,使其能够(分别)const和/或volatile合格的对象.例如,const不能在const对象上调用非方法.这可以被视为方法中的限定this,即void Foo::bar() const具有this类型Foo const*.

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

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

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

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

概念

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

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

C++

在C++中,正如我们先前看到,这是通过使用不同的访问级别(完成public,protectedprivate),并准许访问所述非public水平的代码的限制部分.通常,属性将是私有的,因此只能由类方法访问(对于语法怪癖,可能是某些朋友).

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

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

麻烦的是,因为方法负责维护不变量,所以越多,负责能力就越大,使得追踪错误和确保正确性变得更加困难.此外,由于方法取决于类内部,因此更改成本更高.

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

  • 见萨特采取std::string坝段未穿线.
  • Sutter在其接口原则中强调了对非朋友方法的委派,其中他声明与类(在相同文件/相同名称空间中)一起提供并使用该类的函数在逻辑上是类接口的一部分.他重申了Exceptional C++.

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


Mar*_*utz 18

(非静态)成员函数具有隐式this参数,非成员函数不具有隐式参数.

在语法上,你通过在左边的是隐含参数.->操作者like.so()like->so(),而不是作为一个函数的参数so( like ).

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

class Class {
public:
    void a_public_member_function();
};
Run Code Online (Sandbox Code Playgroud)

非成员函数在任何类之外声明(C++在"命名空间作用域"调用它).

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


Ale*_*ler 9

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

非成员函数没有隐式this.在下面的示例中,bar是成员函数而freebar不是.两者都或多或少相同,但请注意如何bar获取隐式对象指针this(也只有barfoo成员的特权访问权限,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
Run Code Online (Sandbox Code Playgroud)

在语义上,成员函数不仅仅是具有隐式this参数的函数.它的目的是定义行为的对象(即,汽车对象有drive(),stop()作为成员函数).

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


Naw*_*waz 6

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

class Sample
{
  void f();
};

void g();
Run Code Online (Sandbox Code Playgroud)

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