我必须显示无法在c ++中内联的函数.
要检查这个,我有标志-Winline设置.
使用递归函数,我能够生成一个无法内联的函数.
但我尝试使用继承和"虚拟"关键字.但我不能让编译器抱怨内联不可能出现问题.
我知道这个话题已经涵盖了很多.但我没有找到一个有效的例子.我的编译器"聪明":-)
我试过这个:
class virt1
{
public:
virt1(){};
inline virtual int virtFunc(int a){ return a*a; };
virtual ~virt1(){};
};
class virt2 : public virt1
{
public:
virt2(){};
inline virtual int virtFunc(int a){ return a+a;};
virtual ~virt2(){};
};
void testVirtFunc(virt2 &obj)
{
std::cout << obj.virtFunc(2);
}
Run Code Online (Sandbox Code Playgroud)
没有"可倾斜"或"不可倾斜"功能这样的概念.对函数只有无限或无法调用.声明inline的属性是函数本身的属性.无法使用(或不可倾斜)的属性是特定呼叫的属性.这是两个不同的概念.
你似乎在混合这两个完全不相关的概念.
可以声明每个函数inline.可以声明虚函数inline.也可以声明递归函数inline.它没什么奇怪的.你的期望在某种程度上是非法的是完全没有根据的.声明一个函数总是合法的inline.
同时,是否将内联这些函数的实际调用是一个完全不同的独立问题.对某个函数的一次调用可以是无法使用的,而对另一个函数的另一次调用可以是不可嵌入的."无法忍受"再次成为每次通话的财产.
确实,无法内联动态调度的虚拟调用.同时,在智能编译器可以在编译时正确预测虚拟调用中使用的对象的动态类型的情况下,编译器可能会生成对虚函数的直接调用(不使用动态调度的调用).这个电话很容易被内联.
例如,给出您的声明,此调用
virt1 *v = rand() % 2 ? new virt1() : new virt2();
v->virtFunc(5);
Run Code Online (Sandbox Code Playgroud)
无法内联.但这些电话
virt2 v2;
v2.virtFunc(6);
virt1* v1 = &v2;
v1->virtFunc(7);
Run Code Online (Sandbox Code Playgroud)
可以毫无问题地内联.
通过指向函数的指针进行的间接调用通常无法内联.但是如果编译器在编译时以某种方式知道指针的确切值,那么可以用直接调用和内联来替换调用.
递归函数调用也可以内联(尽管你不这么认为).它们可以内联到某个固定的递归深度.这就是大多数编译器内联递归函数的方式:它们使用深度限制内联来"解包"递归,就像它们打开循环一样.