指定内联关键字,基类,派生类或两者都在哪里?

问题描述 投票:2回答:2

假设我们不打算在适用的情况下将编译器提示为内联成员函数。

class Base
{
 public:
      inline virtual f() = 0;
};

class Derived : public Base
{
 public:
      virtual f() override; // no inline specifier here
};

我是否需要在inline中指定Derived::f()或者我可以省略关键字并确保virtual Derived::f()inline Derived::f()相同?

我的意思是为inline隐式指定的Derived::f()关键字,还是我需要再次显式键入它?

c++ inheritance inline virtual
2个回答
3
投票

我是否需要在inline中指定Derived::f()或者我可以省略关键字并确保virtual Derived::f()inline Derived::f()相同?

如果省略派生类中的inline关键字,则派生类中的inline不是。

我的意思是为inline隐式指定的Derived::f()关键字

不它不是。

或者我需要再次明确键入它吗?

是的你是。但是,编译器很可能会为它生成代码,就好像它是一个非inline成员函数,因为它是一个virtual成员函数。


1
投票

What does the inline keyword do?

现代编译器试图平衡函数内联的成本和收益。

好处和成本都很清楚:当一个函数被内联时,函数调用没有开销(因为没有函数调用),并且编译器能够根据上下文对函数体进行优化在其中被调用(因为,当它被内联时,它知道上下文)。

成本可能包括增加的可执行文件大小(如果它是一个很大的功能),并且可执行程序周围的功能正文的程序集的更多实例。

一个经验法则是,如果函数很大或很复杂,它可能不会内联。如果它很小,它可能会被内联。

这很好。它可以防止膨胀的可执行文件,但仍然消除了与使用函数相关的几乎所有开销。执行大型复杂功能的时间通常使函数调用的成本相形见绌,并且内联它只会带来最小的好处。

那么inline做什么?编译器在决定内联函数时计算函数的复杂程度。然后,它将该计算与某个阈值进行比较。如果函数不如阈值复杂,则会内联函数。

inline关键字基本上提高了该特定函数的阈值,但它实际上在引擎盖下的作用因编译器而异。

Can all function calls be inlined?

如果编译器不知道调用了哪个函数,则无法对其进行内联。

我们来看一个例子:

// func_t is a pointer to a function that returns an integer
using func_t = int(*)(); 
int getNumber(func_t func) {
    // The compiler can't inline func(), because it doesn't know
    // what func *is*
    return func(); 
}

How does this apply to virtual functions?

虚函数调用与调用函数指针非常相似,但有一些关键差异。如果从基类调用它,编译器不会提前知道要调用的函数:

class Base {
    virtual int getNum() { return 0; }
};

class Derived {
    int value; 
    void setValue(int v) { value = v; }
    int getNum() override { return value; }
}; 

int getNumFrom(Base& base) {
    // The compiler doesn't know whether to call
    // Base::getNum() or Derived::getNum(), so it can't inline it
    return base.getNum();
}

但是,如果您从类的具体实例(不是引用而不是指针)调用它,则编译器确切地知道调用哪个版本:

int getNumFromDerived() {
    Derived d; 
    // Here, we know that we're calling Derived::getNum()
    // so the compiler *can* inline it. 
    return d.getNum(); 
}

How should you apply the inline keyword?

您可以在基类和派生类中指定它。只知道它不能保证它们被内联,正是因为有时无法内联虚函数调用。

Are there alternatives?

由于模板保留了类型信息,因此编译器始终知道要调用哪个函数。内联模板化函数调用很容易,使用它们不会增加程序的开销。

如果可能,首选模板而不是虚拟继承。

© www.soinside.com 2019 - 2024. All rights reserved.