免责声明:

对于以下样式是否为“良好实践”,我不感兴趣。我正在寻找答案/解决问题的方法。

问题:

我正在cpp文件中编译一个类。编译过程剥夺了我认为是“未使用”的方法定义。有什么办法可以防止这种情况?
 (请参见下面的示例开发环境)

开发环境:

我目前正在使用g++ --std=c++98。完美的解决方案将在所有c ++ 98-standard和更高版本的编译器上可用。

例:

example1.cpp

#include <stdio.h>

class Example1{
    public:
    void print(){printf("helloWorld");};

};


编译,组装和链接该文件不会创建print()方法。 (g++ --std=c++98 example1.cpp main.cpp,其中main.cpp只是调用打印方法。)

对此进行编译(无链接,g++ --std=c++98 -S)将输出:

example1.s

.file   "example1.cpp"
    .text
    .ident  "GCC: (Ubuntu 9.2.1-9ubuntu2) 9.2.1 20191008"
    .section    .note.GNU-stack,"",@progbits
    .section    .note.gnu.property,"a"
    .align 8
    .long    1f - 0f
    .long    4f - 1f
    .long    5
0:
    .string  "GNU"
1:
    .align 8
    .long    0xc0000002
    .long    3f - 2f
2:
    .long    0x3
3:
    .align 8
4:


显然这里没有生成print()方法。

不好的解决方法

如果在同一文件中使用该方法,则可以使编译器生成该方法(请参见下面的代码)。但是,我正在寻找更好的解决方案。也许编译器选项?

example1.cpp

#include <stdio.h>

class Example1{
    public:
    void print(){printf("helloWorld");};

};

// Create a function outside the class, that uses print().
// That way, print will be generated.
void foo(){
    Example1 ex;
    ex.print();
}


 备注(编辑):


在类之外定义方法是没有选择的。
Example1main.cpp中的用法如下:


main.cpp

class Example1{
    public:
        void print();
};

int main(){
    Example1 example;

    example.print();

    return 0;
}

最佳答案

简短的答案是“您不能使用标准C ++”。

更长的答案分为几个部分。

首先,您的解决方法无法实现您认为的目的。


#include <stdio.h>

class Example1{
      public:
      void print(){printf("helloWorld");};
};

// Create a function outside the class, that uses print().
// That way, print will be generated.
void foo(){
    Example1 ex;
    ex.print();
}



这不会阻止编译器“删除”成员函数Example1::print()。没有什么可以阻止编译器在Example1::print()中内联foo()的调用,并且不会(使用您的措辞)以(例如)链接程序可以解决的形式生成该函数。

第二,您的“ main.cpp”


class Example1{
     public:
     void print();
 };

int main(){
      Example1 example;

    example.print();

    return 0;
}



如果将它与“ example1.cpp”的任何一个版本用于同一项目,则会引入未定义的行为,因为类Example1的定义明显不同-一个在类定义中定义成员函数print(),另一个没有。因为您的程序有两个不同的类Example1定义,所以这违反了一个定义规则。

如果您的第二个“ example1.cpp”似乎“有效”(无论您如何评估),那么您就很幸运。未定义行为的性质意味着它似乎可以正常工作。问题是,C ++标准不提供任何此类保证-当行为未定义时,允许编译器执行其喜欢的操作-您的代码似乎可以“起作用”,或者它可以做完全不同的事情。

通常解决这类问题的方法是将类Example1的定义放在单独的头文件中,例如

// example1.h
#include <stdio.h>
class Example1{
      public:
      void print(){printf("helloWorld");};
};


然后将该标头包含在所有需要它的源文件中。例如;

//   example1.cpp

#include "example1.h"

void foo()
{
    Example1 ex;
    ex.print();
}




// main.cpp
#include "example1.h"
int main()
{
    Example1 example;
    example.print();
    return 0;
}


然后,可以在同一程序中安全地使用上面的两个源文件(example1.cpp和main.cpp)。

由于函数Example1::print()是内联定义的,因此编译器可以自由地内联它。仍然不需要编译器进行内联,但是允许这样做。这意味着,生成的目标文件或可执行文件不一定包含任何可识别(例如通过检查程序集)为函数Example1::print()的内容。在您的示例中,在main()foo()中可能仅存在调用printf()的代码,但是没有什么明显地是名为Example1::print()的函数。

作为另一个答案(您拒绝了该答案,随后将其删除),您说可以防止内联的唯一方法是在类定义之外定义函数。该功能定义必须恰好在项目中的一个编译单元中。这允许编译器“生成”功能,但在技术上不要求它(允许智能编译器和链接器“删除”该功能)。

关于c++ - 如果方法是在类中定义的,则防止编译器删除方法,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59278553/

10-10 13:42
查看更多