【问题标题】:Forward Declaring enum class not working前向声明枚举类不起作用
【发布时间】:2013-09-29 03:24:44
【问题描述】:

在 State.h 我有

enum class StateID : unsigned int;

在 State.cpp 我有

enum class StateID : unsigned int
{
    NullID = 0,
    MainMenuID,
    GamePlayID,
};

问题是任何包含State.h 的类都有前向声明,但我不能在任何cpp 文件中使用任何enum 值,除了States.cpp(定义它),比如StateID::MainMenuID。错误说...

/home/lee/Projects/SuddenAwakening/Source/Game.cpp:24:错误:“MainMenuID”不是“StateID”的成员

我正在运行 LinuxMint15KDE、g++ 4.7,并且我在 nullptr、unique_ptr 等其他部分使用 c++11 功能,所以并不是我忘记了 c++11 的编译器标志。

【问题讨论】:

    标签: c++ c++11 forward-declaration enum-class


    【解决方案1】:

    这是因为只有 States.cpp 知道 enum class ID 中存在哪些成员。

    包含 States.hpp 的文件只知道enum class IDunsigned int 的大小,仅此而已。

    您需要在标头中提供枚举值,以便任何需要了解枚举值的文件(例如MainMenuID)都可以使用它们。

    您可以为转发创建一个单独的标头,可能称为 StateFwd.hpp,然后将您的 State.cpp 重命名为 State.hpp .

    您可以在何处/如何转发声明的示例

    根据我们在 cmets 中的讨论,我用一个例子更新了我的答案。

    水果.hpp

    任何选择包含此标题的人都会知道存在什么样的水果。

    #ifndef FRUIT_HPP
    #define FRUIT_HPP
    
    enum class Fruit
    {
        APPLE,
        ORANGE,
        BANANA
    };
    
    #endif
    

    村庄.hpp

    村里到处都是对水果的渴望驱使的人。

    #ifndef VILLAGE_HPP
    #define VILLAGE_HPP
    
    enum class Fruit;
    
    namespace farmer
    {
        bool is_fruit_for_sale(Fruit fruit);
        float get_cost_of_fruit(Fruit fruit);
    }
    
    namespace blind_but_greedy_merchant
    {
        bool sell_fruit(Fruit fruit, float money);
    }
    
    namespace peasant
    {
        inline bool buy_fruit(Fruit fruit, float money)
        {
            return blind_but_greedy_merchant::sell_fruit(fruit, money);
        }
    }
    
    #endif
    

    farmer.cpp

    这个农民只种苹果和橙子,所以他从来没有卖过香蕉

    #include "fruit.hpp"
    
    namespace farmer
    {
        bool is_fruit_for_sale(Fruit fruit)
        {
            switch ( fruit ) {
            case Fruit::APPLE:
            case Fruit::ORANGE:
                return true;
            case Fruit::BANANA:
                return false;
            }
            return false;
        }
    
        float get_cost_of_fruit(Fruit fruit)
        {
            switch ( fruit ) {
            case Fruit::APPLE:
                return 1.00f;
            case Fruit::ORANGE:
                return 2.50f;
            case Fruit::BANANA:
                return 200.0f;
            }
            return 0.0f;
        }
    }
    

    merchant.cpp

    这位商人因贪婪而失明。他再也看不到什么样的 他卖的水果。他仍然知道如何与农民打交道, 将客户要求传递给农民,同时增加巨额利润 所有水果的保证金。 这就是不包含 fruit.hpp 的原因。

    #include "village.hpp"
    
    namespace blind_but_greedy_merchant
    {
        bool sell_fruit(Fruit fruit, float money)
        {
            if ( !farmer::is_fruit_for_sale(fruit) ) {
                return false;
            }
    
            float inflatedcost = farmer::get_cost_of_fruit(fruit) * 3;
    
            if ( money < inflatedcost ) {
                return false;
            }
    
            return true;
        }
    }
    

    example.cpp

    这将所有内容结合在一起。在我们的示例中,我们希望农民去买一些水果。 我们确切地知道我们想要什么样的水果;一根香蕉。因此我们需要包含fruit.hpp,否则我们无法告诉农民去给我们买香蕉。

    在这个场景中,唯一知道存在哪种水果的人是我们(example.cpp)和农民(farmer.cpp)。 农民甚至不需要知道。就像我们给了他一张折叠的纸,上面写着我们想要什么水果,但我们告诉他不要看它。他只是把它交给不会阅读的商人,所以他只是把它传递给农民。

    #include "village.hpp"
    
    #include "fruit.hpp"
    
    int main()
    {
        peasant::buy_fruit(Fruit::BANANA, 25.0f);
    
        return 0;
    }
    

    【讨论】:

    • 根据许多网站,您可以按照我的方式转发声明。这是一个这样的链接。 upto11blog.blogspot.com/2012/12/…
    • @EddieV223 在链接示例的“主程序”中,他们演示了前向声明的目的。该程序知道有一个 Inventory::Fruit 这样的东西,但它仍然不知道是什么样的水果的存在。但是因为它知道有水果这种东西,所以它可以得到水果,并且得到它们的成本。
    • 如何调用 float getCost(Fruit leFruit);无法访问 Fruit 的值?
    • @EddieV223 他们在示例中就是这样做的。他们调用 leInventory.getFruit();。这给了我们一个 Inventory::Fruit。我们不知道它是什么价值,或者它可能是什么价值。您可以分配一个的唯一原因是因为编译器知道枚举类与 int 大小相同,并且您唯一可以用它做的事情就是向其写入 Fruit 值或从中读取 Fruit 值。获得水果的唯一另一种方法是构造一个 (Fruit myfruit;) 或通过静态转换一些值来分配它: Fruit myfruit = static_cast(100);
    • +1 令人回味的例子! “他再也看不到他卖的是什么水果了……这就是为什么不包含fruit.hpp”——天才。
    猜你喜欢
    • 1970-01-01
    • 2023-03-27
    • 1970-01-01
    • 2013-02-14
    • 2011-11-20
    • 1970-01-01
    • 1970-01-01
    • 2010-09-09
    • 1970-01-01
    相关资源
    最近更新 更多