【问题标题】:Vc++/c++ Force Include Header Exceptionvc++/c++ 强制包含头异常
【发布时间】:2015-06-24 08:03:07
【问题描述】:

所以我一直在使用 makefile 和 g++ 在 Linux 中开发一个项目,但现在我想让它在 Visual Studio 上的 Windows 中运行。所以我的项目有一个特殊的 cpp 和 .h 文件。只有 1. 我将 .h 配置为自动将该 .h 文件包含在所有 cpp 文件中,但特殊的 cpp 文件除外。但是,我似乎无法在 Visual Studio 中这样做。

我基本上是在编写自己的 vcxproj 文件,所以我查找了配置设置,并在设置中找到了 Force Include 标志。但我似乎无法找到解决这个例外的方法。

我还尝试修改 .h 文件,以便它可以识别它的包含位置并通过 #if 和“__FILE__”等预处理指令表现出不同的行为。但我发现“__FILE__”会以任何方式返回 .h,而不是源代码。

我在谷歌上搜索的想法和关键字用完了。那么有什么想法或线索吗?

提前致谢。

编辑:

在 Linux 上运行的示例代码:

特殊.h

class Test{
private:
Test() = delete;
Test(const Test&) = delete;
Test(Test&&) = delete;
public:
    void print(const char*);
};
extern TEST t1;

Special.cpp

#include <iostream>
class Test{    //Singleton Class
private:
Test();    //Note that this line is different from the .h
Test(const Test&) = delete;
Test(Test&&) = delete;
public:
    static Test& getInstance();    //Note that this line is missing from the .h
    void print(const char*);
};
Test::Test(){}
Test& Test::getInstace(){
    static Test inst;
    return return inst;
}
void Test::print(const char* msg){
    std::cout << msg << std::endl;
}
Test t1 = Test::getInstance();    

Main.cpp

int main(){
    t1.print("Hello World!");
}

生成文件:

all: App-Main

App-Main: Main.o Special.o
    g++ Main.o Special.o
Special.o: Special.cpp
    g++ -c $< $@ -std=c++11
%.o: %.cpp
    g++ -c $< $@ -std=c++11 -include Special.h

这就是目前在 Linux 中运行的代码。没有构建错误什么都没有。 如果我们在Special.cpp 中包含Special.h,就会出现问题。 现在,请假设有理由不在 cpp 文件中包含 .h 文件。

【问题讨论】:

  • 详细描述好,但不如代码。你能创建一个Minimal, Complete, and Verifiable Example 给我们看吗?如果您遇到构建错误,请您也显示它们吗?
  • 刚刚添加了一个工作示例的示例。我的问题不是构建错误,而是设计问题。我正在寻找一种解决方案,既可以在 Visual Studio 中进行异常处理,也可以将其包含在Special.cpp 中的Special.h 中,但它就像Special.h 为空一样。如果有什么东西可以让编译器忘记之前声明的东西。像#undef 之类的东西。我不知道,我现在只是猜想。

标签: c++ visual-studio visual-c++ makefile


【解决方案1】:

定义Test两个头文件和源文件。去掉源文件中的类定义,只保留成员函数实现。


当你要求预处理器#include 一个文件时,它确实包含了#include 指令位置上的实际内容。

预处理后你的文件看起来像

...
class Test{
public:
    void print(const char*);
};

class Test{
public:
    void print(const char*);
};
void Test::print(const char* msg){
    std::cout << msg << std::endl;
}

【讨论】:

  • 做不到。类齿列实际上在某种意义上是不同的,但链接器认为它们是相同的。嗯,好的,我会尝试修改示例以反映这一点。
  • @DanMaklen 也许你想要the pimpl idiom这样的东西?
  • @DanMaklen 另外,这两个类实际上是两个不同的类。想想如果类有不同的成员变量会发生什么,当编译器(或者你通过new)在头文件中分配类的实例时,源文件中类的成员变量是未知的,并且使用成员源文件中类的变量将导致未定义的行为,因为它们可能根本没有被分配或构造。这可以通过使用我在之前评论中链接到的 pimpl 成语来解决。
  • 从编译器和链接器的角度来看,这是一种有效的语法,如果包含正确,它将正常工作。发生的事情是编译器对每个 cpp 文件进行传递。当它传递Special.cpp 时,它知道有它需要的那些特定功能。当它传递main.cpp 时,它只知道打印功能。所以main.cpp 如果试图构建一个新的编译阶段,它甚至无法通过编译阶段。当链接到来时,它确实在Special.o 中找到了来自main.o 的函数的位置,因此它可以正常工作。
  • @DanMaklen:您所描述的(不同的实现)违反了单一定义规则。不仅定义必须在字面上相同,名称的查找也必须匹配。
【解决方案2】:

最简单的解决方案是在任何地方#include "Special.h"。当然,它有一个头后卫。现在在“Special.cpp”的编译中,也通过/D=SPECIAL_H_HEADERGUARD。标题仍将被物理包含,但在逻辑上被跳过。

当然,您想要这样做的原因(故意违反 ODR)相当可疑,并且无法保证实际结果。例如,链接时间代码生成 (LTCG) 违反了您的“哑链接器”假设。

【讨论】:

    猜你喜欢
    • 2017-10-18
    • 1970-01-01
    • 1970-01-01
    • 2011-11-06
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    相关资源
    最近更新 更多