我正在使用一个小的C ++ WinAPI包装器。我想创建自己的窗口并附加我自己的控件。 我创建了两个类:Window和Control。 问题是我很难处理多个头文件,因为类Control需要类Window,反之亦然。当我编译代码时,我收到很多错误..
以下是我的文件:
globals.h:
// globals.h
// I need this file to define a few constants and to include the main headers needed by my classes
#ifndef GLOBALS_H
#define GLOBALS_H
#include <windows.h>
#include <iostream>
#include <vector>
#include "window.h"
#define SOME_GLOBAL_CONSTANT 1
#endif
window.h:
// window.h
#ifndef WINDOW_H
#define WINDOW_H
#include "globals.h"
#include "control.h"
class Window
{
public:
Window(RECT windowRect);
virtual ~Window();
void appendChild(Control* child);
private:
RECT m_windowRect;
Control m_staticBackground;
std::vector<Control*> m_children;
};
#endif
window.cpp:
// window.cpp
#include "window.h"
Window::Window(RECT windowRect) : m_windowRect(windowRect)
{
std::cout << SOME_GLOBAL_CONSTANT << std::endl;
}
Window::~Window()
{
m_children.clear();
}
void Window::appendChild(Control* child)
{
m_children.push_back(child);
}
control.h:
// control.h
#ifndef CONTROL_H
#define CONTROL_H
#include "globals.h"
class Control
{
public:
Control(Window* parentWindow);
virtual ~Control();
private:
RECT m_controlRect;
Window* m_parentWindow;
};
#endif
control.cpp:
// control.cpp
#include "control.h"
Control::Control(Window* parentWindow) : m_controlRect({}), m_parentWindow(parentWindow)
{
std::cout << SOME_GLOBAL_CONSTANT << std::endl;
}
Control::~Control()
{}
最后,main.cpp:
#include "globals.h"
class MyCustomControl : public Control
{
public:
MyCustomControl(Window* parentWindow) : Control(parentWindow)
{}
~MyCustomControl()
{}
};
class MyWindow : public Window
{
public:
MyWindow(RECT windowRect) : Window(windowRect)
{
kid1 = new MyCustomControl(this);
appendChild(kid1);
}
~MyWindow()
{
delete kid1;
}
private:
MyCustomControl* kid1;
};
int main()
{
MyWindow appWindow;
std::cout << SOME_GLOBAL_CONSTANT << std::endl;
return 0;
}
以下是我得到的所有编译错误:
1>------ Build started: Project: include, Configuration: Debug Win32 ------
1>window.cpp
1>d:\visual studio 2017\projects\include\include\control.h(9): error C2061: syntax error: identifier 'Window'
1>d:\visual studio 2017\projects\include\include\control.h(14): error C2143: syntax error: missing ';' before '*'
1>d:\visual studio 2017\projects\include\include\control.h(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\visual studio 2017\projects\include\include\control.h(14): error C2238: unexpected token(s) preceding ';'
1>main.cpp
1>d:\visual studio 2017\projects\include\include\control.h(9): error C2061: syntax error: identifier 'Window'
1>d:\visual studio 2017\projects\include\include\control.h(14): error C2143: syntax error: missing ';' before '*'
1>d:\visual studio 2017\projects\include\include\control.h(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\visual studio 2017\projects\include\include\control.h(14): error C2238: unexpected token(s) preceding ';'
1>d:\visual studio 2017\projects\include\include\main.cpp(8): error C2664: 'Control::Control(const Control &)': cannot convert argument 1 from 'Window *' to 'const Control &'
1>d:\visual studio 2017\projects\include\include\main.cpp(8): note: Reason: cannot convert from 'Window *' to 'const Control'
1>d:\visual studio 2017\projects\include\include\main.cpp(8): note: No constructor could take the source type, or constructor overload resolution was ambiguous
1>d:\visual studio 2017\projects\include\include\main.cpp(32): error C2512: 'MyWindow': no appropriate default constructor available
1>d:\visual studio 2017\projects\include\include\main.cpp(13): note: see declaration of 'MyWindow'
1>control.cpp
1>d:\visual studio 2017\projects\include\include\window.h(13): error C2061: syntax error: identifier 'Control'
1>d:\visual studio 2017\projects\include\include\window.h(17): error C3646: 'm_staticBackground': unknown override specifier
1>d:\visual studio 2017\projects\include\include\window.h(17): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\visual studio 2017\projects\include\include\window.h(18): error C2065: 'Control': undeclared identifier
1>d:\visual studio 2017\projects\include\include\window.h(18): error C2059: syntax error: '>'
1>d:\visual studio 2017\projects\include\include\window.h(18): error C2976: 'std::vector': too few template arguments
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.10.25017\include\vector(700): note: see declaration of 'std::vector'
1>Generating Code...
1>Done building project "include.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
非常感谢任何帮助。
提前谢谢你,
winapiwrapper。
编辑:我还阅读了this thread,但我无法解决问题。
答案 0 :(得分:1)
将"window.h"
从globals.h
移至controls.cpp
。并将class Window;
放在class Controls {
controls.h
之前。这称为forward declaration。
您甚至不需要window.h
中的controls.cpp
,您可以将其直接移至main.cpp
。
答案 1 :(得分:1)
欢迎编程。删除一条错误消息,两条消息取代它。
嗯......不是真的。当你解决一个错误时,发生了什么,这揭示了这些错误隐藏的错误。
首先是PSA:
在没有编译和测试的情况下,不要编写很多代码。这样,当出现问题时,您需要检查较少量的代码。从main
函数开始。确保它构建。添加您需要的标头。确保它构建。为main
编写一个函数来调用。确保它构建。重复直到程序结束。试图一次性添加太多会导致像您在这里遇到的级联风暴错误。
全局包含头文件通常是一个傻瓜赌注。它们经常引导你遇到诸如你在这里的循环依赖之类的问题,并且即使他们不必要,也会使文件包含所有内容。这可以减慢构建时间。
接下来,请在继续之前阅读以下链接:Resolve header include circular dependencies
现在回答:
window.h包含control.h。控制.h包括window.h尽管global.h。这导致上述链接中讨论的鸡和蛋问题。其中一个标题将被包含在另一个之前,并且无法找到另一个文件的内容。幸运的是,control.h只需要引用Window
,而不是整个事情,这可以通过前向声明和删除全局包含文件来满足。
我不打算证明清理它。该过程在链接中有详细记录。
这暴露了头号2:Window
包含Control m_staticBackground
并且未明确初始化它。这导致编译器寻找Control
的默认构造函数,这是不存在的。
解决方案:明确初始化m_staticBackground
Window::Window(RECT windowRect) : m_windowRect(windowRect),
m_staticBackground(this)
{
std::cout << SOME_GLOBAL_CONSTANT << std::endl;
}
BIG Mother Freaking note在这里说:m_staticBackground(this)
狡猾得很厉害。 this
还没有完全构建,所以如果你做的不仅仅是将它存储在Control::Control
(这就是你现在正在做的事情)非常糟糕,那么就会发生不可预测的事情。 请勿在{{1}}构造函数的正文中使用 parentWindow
或m_parentWindow
。如果可能的话,找到一种更好,更安全的方法来做到这一点。如果不可能,请使用“请勿使用”消息进行记录,以提醒未来的自己或其他任何查看代码的人不要使用它们。
修复后,您将进入
Control
在MyWindow appWindow;
。 main
的构造函数需要MyWindow
您目前没有RECT
提供,所以我会在此停止。