新库中带有 cpp 文件的 ifndef

ifndef with cpp file in new library

你好,我正在尝试用 C++ 构建我自己的库,经过许多小时的搜索和尝试,我了解到一个好的方法是使用嵌套 classes,所以我在这种形式的树: file tree

所以我将所有 class 文件分成不同的 header 文件(我知道这更难,也许没有必要,但我想这样,如果没有别的,那就只是为了训练) .因此,为了保持嵌套的 class 连接,但在不同的文件中,每个 header 都需要包含其 child 和/或 parent 才能正常运行。这没有用,给了我递归包含错误(duh)所以我在网上搜索并找到了#ifndef 和#define 并且我以这种方式使用它们:

    //A.hpp
    #ifndef A_HPP_INCLUDED   // some unique macro
    #define A_HPP_INCLUDED

    class A
    {
    public:
        class B;
        class C;
        
    };
    #include "B.hpp"
    #include "C.hpp"
    #endif

    //B.hpp
    #ifndef B_HPP_INCLUDED
    #define B_HPP_INCLUDED

    #include "A.hpp"
    class A::B
    {
    public:
        static int num;
        void func();
    };
    #endif
    int A::B num = 5;

    //C.hpp
    #ifndef C_HPP_INCLUDED   // some unique macro
    #define C_HPP_INCLUDED

    #include "A.hpp"
    class A::C
    {
    public:
        void func();
    };
    #endif

但是第二次我将#include "B.hpp" 添加到 B.cpp 文件中,它立即给我错误,我以这种方式添加的所有变量和函数都被定义了多次。没有 cpp 文件,它工作得很好,但有了它们,它就会崩溃。事实上,将任何 cpp 文件添加到任何 header

时都会发生这种情况

欢迎回答此问题,但如果您有任何关于如何以更好的方式制作库文件的提示,甚至只是随机提示,那就太棒了!

仅供参考,我正在使用 qt creator、qmake、c++11。如果需要 qmake 文件,我会发送它,但我认为那里的一切都很好。

有问题的文件(用于重现问题):

    //testlibrary.hpp

    #ifndef TESTLIBRARY_HPP_INCLUDED   // some unique macro
    #define TESTLIBRARY_HPP_INCLUDED

    class TestLibrary
    {
    public:
        class Core;
        class SFML;
    };
    #include <Core/Core.hpp>
    #include <SFML++/SFMLpp.hpp>
    #endif


    //Core.hpp
    #pragma once

    #ifndef CORE_HPP_INCLUDED   // some unique macro
    #define CORE_HPP_INCLUDED

    #include <testlibrary.hpp>

    class TestLibrary::Core
    {
    public:
        class Constants;
    };
    #include "Constants.hpp"
    #endif


    //Constants.hpp
    #pragma once
    #ifndef CONSTANTS_HPP_INCLUDED   // some unique macro
    #define CONSTANTS_HPP_INCLUDED
    #include "Core.hpp"
    class TestLibrary::Core::Constants
    {
    public:
        static float const_PI;
        static float const_Euler;
        Constants();
    };
    float TestLibrary::Core::Constants::const_PI = 3.1415;
    float TestLibrary::Core::Constants::const_Euler = 2.71828;
    #endif


    //SFMLpp.hpp
    #pragma once
    #include <SFML/Window.hpp>
    #include <SFML/Graphics.hpp>
    #ifndef SFML_HPP_INCLUDED   // some unique macro
    #define SFML_HPP_INCLUDED
    #include <testlibrary.hpp>
    class TestLibrary::SFML
    {
    public:
        class Text;
    };

    //#include "Text.hpp"
    #endif


    //Text.hpp
    #pragma once

    #ifndef TEXT_HPP_INCLUDED   // some unique macro
    #define TEXT_HPP_INCLUDED
    #include "SFMLpp.hpp"
    class TestLibrary::SFML::Text : public sf::Text
    {
    public:
        sf::Font font_;

        Text();
        Text(std::string string);
        Text(std::string string, sf::Font &font);
        Text(std::string string, sf::Font &font, int size);
        Text(std::string string, sf::Font &font, int size, sf::Color color);

        void setTextInt(int inputText);
        void drawText(sf::RenderWindow &window);
    };

    #endif


    //text.cpp
    #include "text.hpp"

静态变量在整个程序中只能定义一次。如果您在头文件中定义它们,则它们会在包含该头文件的每个 .cpp 文件中定义。

将这些行移动到 .cpp 文件中:

float TestLibrary::Core::Constants::const_PI = 3.1415;
float TestLibrary::Core::Constants::const_Euler = 2.71828;

或使用constexpr就地定义它们:

class TestLibrary::Core::Constants
{
public:
    static constexpr float const_PI = 3.1415;
    static constexpr float const_Euler = 2.71828;

在头文件中你应该只有声明(模板除外,但这里不是这种情况),声明如下:

float TestLibrary::Core::Constants::const_PI = 3.1415;
float TestLibrary::Core::Constants::const_Euler = 2.71828;

是定义,这就是你出错的原因。这些语句应该在一些 c++ 文件中。