在基类体内声明但通过派生类调用的函数的内联

Posted

技术标签:

【中文标题】在基类体内声明但通过派生类调用的函数的内联【英文标题】:Inlining of functions declared inside the base class body but called through a derived class 【发布时间】:2017-03-04 20:29:16 【问题描述】:

情况是这样的。我在头文件中声明了一个基类,其中包含一些受保护的数据成员和一些公共 getter 函数(单行正文)。没有虚拟方法。从它派生出一个子类,并定义了自己的构造函数,其定义放在对应的cpp文件中。

是否会内联通过派生类的对象调用 getter 函数?

编辑:这是我的代码。

// quad.h
class QuadratureRule 
protected:
  int ngauss;
  Array points;
  Array weights;
public:
  QuadratureRule(int ng) : ngauss(ng)  
  double getweights(int ig) const 
    return weights[ig];
  
;
class Quadrature2D : public QuadratureRule 
public:
  Quadrature2D(int ng);
;

//quad.cpp
#include "quad.h"
Quadrature2D::Quadrature2D(int ng) : QuadratureRule(ng) 
  // initialize arrays in a certain way

Quadrature2D 类的对象调用时,我希望 getweights 内联。 另外,我使用的是 GCC g++ 5.4 和 6.3。

【问题讨论】:

虽然您的问题可能很清楚,但代码能说明问题。可以提供代码演示吗? 很可能,是的。唯一确定的方法是检查生成的代码。 (没有 C++ 需要函数内联的情况;这取决于实现。) 没有理由不应该内联您的代码,在这方面,与其他函数相比,您的情况并没有什么特别之处。但是,不能保证函数会被内联。只需检查您的装配即可。 【参考方案1】:

编辑:

我一直在检查它,似乎如果你打开优化它实际上会被内联。但正如人们在 cmets 中已经说过的那样,这真的取决于实施。例子:

Code without optimizations

Code with optimizations


你让我很好奇,所以我查了一下。 这是我的程序:

// base.h
include <iostream>

class Base 
    int x;
    int y;
public:
    Base(int x = 0, int y = 0) : x(x), y(y) 
    int getx() const  return x; 
    void setx(int x)  this->x = x; 
    int gety() const  return y; 
    void sety(int y)  this->y = y; 
;

还有:

// derived.cpp
#include "base.h"

class Derived : public Base 
    int z;
public:
    Derived(int x = 0, int y = 0, int z = 0) : Base(x, y), z(z) 
;

using namespace std;

int main() 
    Derived d(1, 2, 3);
    cout << "d.x == " << d.getx() << ", d.y == " << d.gety() << endl;
    d.setx(4);
    d.sety(4);
    cout << "d.x == " << d.getx() << ", d.y == " << d.gety() << endl;
    return 0;

在 gcc 6.3 上编译:

g++ -Wall -Werror -g -pedantic-errors -o derived derived.cpp

这是 objdump 的一部分,在 main() 内:

a2b:   e8 1a 01 00 00          call   b4a <_ZN4Base4setxEi> ; A call to setx()
a30:   48 8d 45 e0             lea    rax,[rbp-0x20]
a34:   be 04 00 00 00          mov    esi,0x4
a39:   48 89 c7                mov    rdi,rax
a3c:   e8 33 01 00 00          call   b74 <_ZN4Base4setyEi> ; A call to sety()
a41:   48 8d 45 e0             lea    rax,[rbp-0x20]
a45:   48 89 c7                mov    rdi,rax
a48:   e8 15 01 00 00          call   b62 <_ZNK4Base4getyEv> ; A call to gety()
a4d:   89 c3                   mov    ebx,eax
a4f:   48 8d 45 e0             lea    rax,[rbp-0x20]
a53:   48 89 c7                mov    rdi,rax
a56:   e8 df 00 00 00          call   b3a <_ZNK4Base4getxEv> ; A call to getx()

假设我没有忽略任何重要的事情,我猜你不能相信你的代码是内联的。

【讨论】:

以上是关于在基类体内声明但通过派生类调用的函数的内联的主要内容,如果未能解决你的问题,请参考以下文章

在基类中存储指向派生类函数的指针

析构函数 声明为protected

警告: deleting object of polymorphic class type which has non_virtual destructor

C++:如何前向声明出现在基类的静态方法中的派生类?

为啥在基类构造函数中看不到派生类属性值?

多态虚函数表底层实现多重继承的问题及处理