Optimization of virtual function calls in a derived class

What is the best way to call virtual functions in a derived class so that the compiler can inline or otherwise optimize the call?

Example:

class Base {
  virtual void foo() = 0;
};

class Derived: public Base {
  virtual void foo() {...}
  void bar() {
    foo();
  }
};

I want the challenge foo()to bar()always cause Derived::foo(). I understand that the call will cause the search in vtable, and the compiler will not be able to optimize it, since there may be another class that inherits from Derived.

I could explicitly call Derived::foo(), but it becomes verbose if Derived has many virtual function calls. It also seems surprising to me that I could not find a lot of material on the Internet, referring to what seems to me to be commonplace (a “final” derived class that calls virtual methods), so I wonder if I am abusing here virtual features or overly optimized.

How to do it? Stop premature optimization and stick foo(), suck it and use Derived::foo(), or is there a better way?

+4
source share
4 answers

++ 11 final, ", ". 1.

, g++ , final.

:

virtualFunctions.h

#pragma once
class Base {
public:
  virtual void foo();
  virtual void bar();
  virtual void baz();
  int fooVar, barVar, bazVar;
};
class Derived: public Base {
public:
  void test();
  virtual void foo();
  virtual void bar();
  virtual void baz() final;
};

virtualFunctions.cpp:

#include "virtualFunctions.h"
void Derived::test() {
  foo();
  Derived::bar();
  baz();
}
void Derived::foo() {
  fooVar = 101;
}
void Derived::bar() {
  barVar = 202;
}
void Derived::baz() {
  bazVar = 303;
}

g++ 4.7.2 -O1 :

_ZN7Derived4testEv:
.LFB0:
    .loc 1 3 0
    .cfi_startproc
.LVL3:
    pushl   %ebx
.LCFI0:
    .cfi_def_cfa_offset 8
    .cfi_offset 3, -8
    subl    $24, %esp
.LCFI1:
    .cfi_def_cfa_offset 32
    movl    32(%esp), %ebx      ; Load vtable from the stack
    .loc 1 4 0
    movl    (%ebx), %eax        ; Load function pointer from vtable
    movl    %ebx, (%esp)
    call    *(%eax)             ; Call the function pointer
.LVL4:
    .loc 1 5 0
    movl    %ebx, (%esp)
    call    _ZN7Derived3barEv   ; Direct call to Derived::bar()
.LVL5:
    .loc 1 6 0
    movl    %ebx, (%esp)
    call    _ZN7Derived3bazEv   ; Devirtualized call to Derived::baz()

Derived::bar() Derived::baz() , vtable foo().

+5

, , .

. , . , , .

, . , .

+3

, . ++ 11, Derived / foo()/bar() , .

+2

- , :

class Derived: public Base {
  virtual void foo() {...}
  void bar() {
    Derived::foo();          // no dynamic dispatch
  }
};

, ( !) . - . , - MoreDerived, foo , bar MoreDerived::foo, , .

, , - , . , , .

0

Source: https://habr.com/ru/post/1540766/


All Articles