相互依赖的类和继承

时间:2017-06-09 23:56:06

标签: c++ windows inheritance visual-studio-2017

我正在使用一个小的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,但我无法解决问题。

2 个答案:

答案 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​​}}构造函数的正文中使用 parentWindowm_parentWindow。如果可能的话,找到一种更好,更安全的方法来做到这一点。如果不可能,请使用“请勿使用”消息进行记录,以提醒未来的自己或其他任何查看代码的人不要使用它们。

修复后,您将进入

Control

MyWindow appWindow; main的构造函数需要MyWindow您目前没有RECT提供,所以我会在此停止。