In C++, how can I avoid #including a header file w

2019-03-29 19:25发布

In my C++ header files I try to use forward declarations (class MyClass;) instead of #including the class header, as recommended in many C++ coding standards (the Google C++ Style Guide is one).

Unfortunately, when I introduce enumerations, I can't do the forward declaration any more. Like this:

//// myclass1.hpp ////

class MyClass1
{
    enum MyEnum1
    {
        Enum_A, Enum_B, Enum_C
    };
};

//// myclass2.hpp ////

// I want to avoid this
#include "myclass1.hpp"

// I'd prefer to do this (forward declaration)
class MyClass1;

class MyClass2
{
    // This is o.k.: I only need to forward declare MyClass1
    MyClass1* ptr;

    // This forces me to #include, but I don't want to!
    void func( MyClass1::MyEnum1 e );
};

The best solution I can think of so far is to replace enums with member constants:

//// myclass1.hpp  ////

MyClass1
{
    static const int Enum_A;
    static const int Enum_B;
    static const int Enum_C;
};

//// myclass1.cpp ////

const int Enum_A = 1;
const int Enum_B = 2;
const int Enum_C = 3;

In this case, though, the solution seems worse than the problem.

I'm currently looking through Large Scale C++ Software Design (Lakos) and Working Effectively with Legacy Code (Feathers) for dependency breaking techniques, but I haven't found a good solution yet.

8条回答
The star\"
2楼-- · 2019-03-29 19:33

You can use template arguments to program against 'general' enum types. Much like this:

// enum.h
struct MyClass1 { enum e { cE1, cE2, cELast }; };

// algo.h
// precondition: tEnum contains enumerate type e
template< typename tEnum > typename tEnum::e get_second() { 
    return static_cast<typename tEnum::e>(1); 
}

// myclass1.h

// myclass.h
template< typename tClass1 >
class MyClass2
{
    tClass1 * ptr;
    void func( tClass1::e e );
};
// main.cpp
#include "enum.h"
#include "algo.h"
int main(){ return get_second<Enum>(); }
查看更多
疯言疯语
3楼-- · 2019-03-29 19:35

You cannot forward declare enum values - and your workaround is a step down the path to complete madness.

Are you experiencing any major compilation slowdowns caused by #including headers? If not, just #include them. Use of forward declarations is not "best practice" it is a hack.

查看更多
劳资没心,怎么记你
4楼-- · 2019-03-29 19:42

This is difficult to do nicely. Perhaps moving enums to a common header file would be a reasonable solution?

Edit: I know the question asked to avoid including a header file, but there's just no way (AFAIK) to do this. Moving enums to a separate header file at least minimises the amount of stuff in the header file you do need to include. It's certainly better than the craziness suggested in the question!

查看更多
啃猪蹄的小仙女
5楼-- · 2019-03-29 19:44

C++0x's strongly typed enums can be forward declared. GCC 4.4.0 and CodeGear C++Builder 2009 support strongly typed enums.

There are a few enum-like classes floating around like the (proposed but never finalized and accepted) Boost.Enum available for download from the Boost Vault at this link. Since Boost.Enums are classes, they can be forward declared.

However, just putting enums in a separate file (as in this answer) seems the simplest, best solution (barring C++0x suport).

查看更多
三岁会撩人
6楼-- · 2019-03-29 19:50

I don't think (I can be proven incorrect) that you can forward declare an internal type, nor an enumeration. You will need the definition of the enclosing class to use the enum.

While most style guides enforce not including unnecessary headers, in your case the header is necessary. Other options you can consider if you really want to avoid the inclusion would be defining the enumeration outside of the class and including the header that defines the enum.

查看更多
劫难
7楼-- · 2019-03-29 19:52

Forward declaration of enumerations has actually been proposed by the C++ standards committee. See this paper (pdf). It would certainly be a good feature!

查看更多
登录 后发表回答