C++ C++;:包含标题(不允许类型不完整)
好的,在你们把我引向不同的帖子之前,这个问题已经被解决了,我想声明,在这篇帖子之后,我确实解决了我的问题 这篇文章更多的是关于如何挖掘编译器工作的表面之下 我们走吧 Menu.h包括MenuEntry.h和MenuEntryKey.h,如下所示:C++ C++;:包含标题(不允许类型不完整),c++,include,C++,Include,好的,在你们把我引向不同的帖子之前,这个问题已经被解决了,我想声明,在这篇帖子之后,我确实解决了我的问题 这篇文章更多的是关于如何挖掘编译器工作的表面之下 我们走吧 Menu.h包括MenuEntry.h和MenuEntryKey.h,如下所示: #ifndef MENU_H #define MENU_H #include <cstdlib> #include <map> #include <string> #include "MenuEntry.h" #
#ifndef MENU_H
#define MENU_H
#include <cstdlib>
#include <map>
#include <string>
#include "MenuEntry.h"
#include "MenuEntryKey.h"
class Menu
{
public:
// ctor, dtor, copy control
Menu(const std::map<MenuEntryKey, MenuEntry> &opts = std::map<MenuEntryKey, MenuEntry>(),
const unsigned numF = 0, const unsigned numD = 0) : options_(opts),
numFoodOptions_(numF),
numDrinkOptions_(numD) {}
~Menu() {}
Menu(const Menu &);
Menu &operator=(const Menu &);
// entry select funcs: both simply return a random menu selection's name, based on the provided entry type.
inline const std::string selectOption(const char);
private:
const std::map<MenuEntryKey, MenuEntry> options_;
const unsigned numFoodOptions_;
const unsigned numDrinkOptions_;
// private accessors; Guests must only be able to select a valid option. This can be changed later, if need be.
inline const std::map<MenuEntryKey, MenuEntry> &getOptions() const { return options_; }
inline const std::map<MenuEntryKey, MenuEntry> &getOptions()
{
return (static_cast<const Menu &>(*this)).getOptions();
}
inline const unsigned getNumFoodOptions() const { return numFoodOptions_; }
inline const unsigned getNumDrinkOptions() const { return numDrinkOptions_; }
};
#endif // MENU_H
#ifndef DATALOADER_H
#define DATALOADER_H
#include <iostream>
#include <fstream>
#include <map>
#include <vector>
#include <ctype.h>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include "Menu.h"
// Note the missing includes that used to be here.
// "" ""
class Menu;
namespace DataLoader
{
const Menu &createMenu();
} // namespace DataLoader
#endif // DATALOADER_H
Menuntry.h:
#ifndef MENUENTRY_H
#define MENUENTRY_H
#include <string>
class MenuEntry
{
const std::string name_;
};
#endif // MENUENTRY_H
DataLoader.h:
#ifndef DATALOADER_H
#define DATALOADER_H
#include <iostream>
#include <fstream>
#include <map>
#include <vector>
#include <ctype.h>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include "Menu.h"
#include "MenuEntryKey.h"
#include "MenuEntry.h"
class Menu;
namespace DataLoader
{
const Menu &createMenu();
} // namespace DataLoader
#endif // DATALOADER_H
#ifndef DATALOADER_H
#define DATALOADER_H
class Menu;
namespace DataLoader
{
const Menu &createMenu();
} // namespace DataLoader
#endif // DATALOADER_H
DataLoader.cpp:
#include "DataLoader.h"
const Menu &DataLoader::createMenu()
{
std::ifstream in;
in.open("../../../../meta/menu.md");
if (!in)
{
std::cout << "Unable to open file.\n";
exit(-1);
}
std::map<MenuEntryKey, MenuEntry> options;
std::string line;
while (std::getline(in, line))
{
if (line.size() == 0)
continue;
if (line[0] == '-')
{
char entryType = toupper(line[1]);
unsigned num = 0;
std::vector<std::string> tokens;
std::getline(in, line);
while (line[0] != '^')
{
boost::algorithm::split(tokens, line, boost::algorithm::is_any_of(" "));
MenuEntryKey key; //INCOMPLETE TYPE ERROR HERE
}
}
} // end while
}
#include "DataLoader.h"
#include "Menu.h"
// #include "MenuEntry.h"
// #include "MenuEntryKey.h"
const Menu &DataLoader::createMenu()
{
MenuEntryKey key;
}
令人惊讶的是,这个框架示例没有产生不完整的类型错误。注意,这两个include语句被注释掉了
为什么现在这样做有效,而以前没有?它必须与包含的标题有关;STL标头包含是否会导致此问题,或者仅包含用户定义的标头?会有警卫阻止这种事情发生吗
感谢您的帮助,我真的很感激。与编译器的工作方式相比,包含内容的工作方式更像是预处理器如何工作的问题。编译器根本不处理
#include
。在将结果传递给编译器之前,所有这些都由预处理器处理。记住C++编译是在不同的阶段完成的;首先进行预处理,然后进行编译(编译本身包括几个阶段:解析、优化、代码生成),然后汇编器生成一个目标文件,链接器然后将目标文件合并到库或可执行文件中代码>只需要声明菜单
。当需要执行时,所有的#include
都应该放在cpp中。@如果您重视快速编译项目,请尝试减少标题中的include。如果可能,首选转发声明,并且只在源文件中包含完整的头。有时,您必须在标题中包含完整的标题/类型定义,但在绝对需要时继续这样做。就像您永远不应该将using namespace…
放在头中一样,因为它会污染头的所有用户,头中不必要的包含会导致该头的所有用户中不必要的包含。在一个大型项目中,这可能意味着编译时间的巨大放缓。#include
主要是复制粘贴文件内容。对于include-guard(很好)和循环依赖(必须避免),include的顺序很重要。(>表示#此处包含)带有menu.h->menu.h(->menu.h)由于包含保护而被丢弃,但从menu.h的角度来看,却丢失了。而menu.h->menu.h->(->menu.h)被丢弃[…])在其他方面存在问题。请提供一个,删除任何不相关的代码并提供所有代码,我无法用给定的代码重现此问题:。我怀疑在您的某个标头中包含防护将是重复的。
#ifndef DATALOADER_H
#define DATALOADER_H
class Menu;
namespace DataLoader
{
const Menu &createMenu();
} // namespace DataLoader
#endif // DATALOADER_H
#include "DataLoader.h"
#include "Menu.h"
// #include "MenuEntry.h"
// #include "MenuEntryKey.h"
const Menu &DataLoader::createMenu()
{
MenuEntryKey key;
}