相互依赖的类和继承
Mutually dependent classes and inheritance
我正在研究一个小C++WinAPI包装器。我想创建自己的窗口并将自己的控件附加到其中。 我创建了2个类:窗口和控件。 问题是我很难处理多个头文件,因为类控件需要类窗口,反之亦然。当我编译我的代码时,我收到很多错误。
这是我的文件:
全局.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
窗口.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
窗口.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);
}
控制.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
控制.cpp :
// control.cpp
#include "control.h"
Control::Control(Window* parentWindow) : m_controlRect({}), m_parentWindow(parentWindow)
{
std::cout << SOME_GLOBAL_CONSTANT << std::endl;
}
Control::~Control()
{}
最后,主要.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 2017projectsincludeincludecontrol.h(9): error C2061: syntax error: identifier 'Window'
1>d:visual studio 2017projectsincludeincludecontrol.h(14): error C2143: syntax error: missing ';' before '*'
1>d:visual studio 2017projectsincludeincludecontrol.h(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:visual studio 2017projectsincludeincludecontrol.h(14): error C2238: unexpected token(s) preceding ';'
1>main.cpp
1>d:visual studio 2017projectsincludeincludecontrol.h(9): error C2061: syntax error: identifier 'Window'
1>d:visual studio 2017projectsincludeincludecontrol.h(14): error C2143: syntax error: missing ';' before '*'
1>d:visual studio 2017projectsincludeincludecontrol.h(14): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:visual studio 2017projectsincludeincludecontrol.h(14): error C2238: unexpected token(s) preceding ';'
1>d:visual studio 2017projectsincludeincludemain.cpp(8): error C2664: 'Control::Control(const Control &)': cannot convert argument 1 from 'Window *' to 'const Control &'
1>d:visual studio 2017projectsincludeincludemain.cpp(8): note: Reason: cannot convert from 'Window *' to 'const Control'
1>d:visual studio 2017projectsincludeincludemain.cpp(8): note: No constructor could take the source type, or constructor overload resolution was ambiguous
1>d:visual studio 2017projectsincludeincludemain.cpp(32): error C2512: 'MyWindow': no appropriate default constructor available
1>d:visual studio 2017projectsincludeincludemain.cpp(13): note: see declaration of 'MyWindow'
1>control.cpp
1>d:visual studio 2017projectsincludeincludewindow.h(13): error C2061: syntax error: identifier 'Control'
1>d:visual studio 2017projectsincludeincludewindow.h(17): error C3646: 'm_staticBackground': unknown override specifier
1>d:visual studio 2017projectsincludeincludewindow.h(17): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:visual studio 2017projectsincludeincludewindow.h(18): error C2065: 'Control': undeclared identifier
1>d:visual studio 2017projectsincludeincludewindow.h(18): error C2059: syntax error: '>'
1>d:visual studio 2017projectsincludeincludewindow.h(18): error C2976: 'std::vector': too few template arguments
1>c:program files (x86)microsoft visual studio2017communityvctoolsmsvc14.10.25017includevector(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。
编辑:我也阅读了这个线程,但我无法解决我的问题。
欢迎来到编程。删除一条错误消息,两条错误消息将取而代之。
井。。。没有。正在发生的事情是,当您解决一个错误时,这揭示了珍贵错误隐藏的错误。
首先是公益广告:
不要在没有编译和测试的情况下编写太多代码。这样,当出现问题时,您需要检查的代码量更少。从main
函数开始。确保它构建。添加所需的标头。确保它构建。编写一个函数供main
调用。确保它构建。重复直到程序完成。尝试一次添加太多会导致一连串的错误风暴,就像您在这里遇到的那样。
全局包含头文件通常是一个傻瓜。它们经常导致您遇到诸如此处的循环依赖关系之类的问题,并使文件包含所有内容,即使它们不必包含。这可能会减慢构建时间。
接下来,在继续之前阅读以下链接:解析标头包含循环依赖项
现在回答:
window.h 包括 control.h. control .h包括 window.h 虽然 global.h.这导致了上面链接中讨论的鸡和蛋问题。其中一个标头将包含在另一个标头之前,并且无法找到另一个文件的内容。幸运的是,control.h 只需要对Window
的引用,而不是整个事情,这可以通过前向声明和删除全局包含文件来满足。
我不会演示清理它。该过程在链接中详细记录。
这暴露了 hydra 头号 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;
}
大妈妈在这里吓坏了:m_staticBackground(this)
狡猾得要命。this
还没有完全构建,所以如果你做的不仅仅是把它存储在Control::Control
(这就是你目前正在做的全部),就会发生非常糟糕、不可预测的事情。请勿使用parentWindow
或m_parentWindow
Control
构造函数的主体内部。如果可能的话,找到一种更好、更安全的方法。如果不可能,请用"请勿使用"消息记录它,以提醒您未来的自己或其他查看代码的人不要使用它们。
修复此问题后,您可以
MyWindow appWindow;
在main
.MyWindow
的构造函数需要一个您当前没有RECT
提供的RECT
,所以我就到此为止。
将"window.h"
从globals.h
移动到controls.cpp
。并把class Window;
放在class Controls {
之前controls.h
.这称为前向声明。
您甚至不需要controls.cpp
中的window.h
,您可以将其直接移动到您的main.cpp
。
- 初始化依赖于子类的继承类的常量类成员
- 循环依赖,在继承类的情况下使用覆盖方法
- 当依赖关系和依赖关系都是多态时,在哪个继承级别存储依赖关系指针?
- 正在从继承中解析循环依赖项
- 继承依赖类型定义而不使用结构
- 相互依赖的类和继承
- C++ 上的循环依赖和继承编译错误
- 模板类型依赖和继承
- 依赖注入/继承设计模式的构造函数参数太多
- 如何在Visual Studio中将项目依赖项/引用从一个项目继承到依赖项目
- C++中对继承的循环依赖
- 依赖类的C++继承和实例化
- 在多继承编译器的情况下访问成员变量是否依赖?如何正确地做
- 如何在C++中管理并行的依赖继承
- C++相互依赖的类的继承
- C++循环依赖和继承
- 处理对继承的循环依赖
- 模板继承:没有依赖模板形参的实参
- 具有继承模板类的循环依赖关系
- 如何使继承依赖