Forward deklarowanie enum w C++

Próbuję zrobić coś takiego:

enum E;

void Foo(E e);

enum E {A, B, C};

Które kompilator odrzuca. Rzuciłem okiem na Google i konsensus wydaje się być "nie można tego zrobić", ale nie mogę zrozumieć, dlaczego. Czy ktoś może to wyjaśnić?

Wyjaśnienie 2: robię to, ponieważ mam prywatne metody w klasie, które przyjmują wspomniane enum i nie chcę, aby wartości enum były eksponowane - więc, na przykład, nie chcę, aby ktokolwiek wiedział, że E jest zdefiniowane jako

enum E {
    FUNCTIONALITY_NORMAL, FUNCTIONALITY_RESTRICTED, FUNCTIONALITY_FOR_PROJECT_X
}

Ponieważ Projekt X jest nie chcę, aby moi użytkownicy wiedzieli o tym.

Tak więc, chciałem forward declare the enum, aby móc umieścić prywatne metody w pliku nagłówkowym, zadeklarować enum wewnętrznie w cpp i rozpowszechnić zbudowany plik biblioteki i nagłówek ludziom.

Co do kompilatora-to GCC.

 277
Author: Cœur, 2008-09-16

18 answers

Powodem, dla którego nie Można zadeklarować enum jest to, że bez znajomości wartości kompilator nie może znać miejsca wymaganego dla zmiennej enum. Kompilatory C++ mogą określać rzeczywistą przestrzeń dyskową na podstawie rozmiaru niezbędnego do przechowywania wszystkich podanych wartości. Jeśli wszystko, co jest widoczne, to deklaracja forward, Jednostka tłumaczenia nie może wiedzieć, jaki rozmiar pamięci zostanie wybrany - może to być znak lub int, lub coś innego.


Z Sekcji 7.2.5 normy ISO C++:

podstawowy typ wyliczenia jest typem całkowym, który może reprezentować wszystkie wartości wyliczenia zdefiniowane w wyliczeniu. Jest to implementacja zdefiniowana, który typ całkowy jest używany jako typ bazowy dla wyliczenia, z wyjątkiem tego, że typ bazowy nie może być większy niż int, chyba że wartość wyliczenia nie może zmieścić się w int lub unsigned int. Jeśli enumerator-list jest pusty, typ bazowy jest tak, jakby wyliczenie miało pojedynczy licznik o wartości 0. Wartość sizeof() zastosowana do typu wyliczenia, obiektu typu wyliczenia lub enumeratora jest wartością sizeof() zastosowaną do typu bazowego.

Ponieważ wywołujący do funkcji musi znać rozmiary parametrów, aby poprawnie ustawić stos wywołań, liczba wyliczeń na liście wyliczeń musi być znana przed prototypem funkcji.

Update: W C++0x składnia foreward deklarowanie typy enum zostały zaproponowane i zaakceptowane. Możesz zobaczyć propozycję na http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2764.pdf

 227
Author: KJAWolf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-09 04:13:05

Forward declaration of enums jest możliwe od C++11. Wcześniej, powodem, dla którego typy enum nie mogły być zadeklarowane do przodu, było to, że rozmiar enumeracji zależy od jego zawartości. Tak długo, jak wielkość wyliczenia jest określona przez aplikację, można ją zadeklarować dalej:

enum Enum1;                   //Illegal in C++ and C++0x; no size is explicitly specified.
enum Enum2 : unsigned int;    //Legal in C++0x.
enum class Enum3;             //Legal in C++0x, because enum class declarations have a default type of "int".
enum class Enum4: unsigned int; //Legal C++0x.
enum Enum2 : unsigned short;  //Illegal in C++0x, because Enum2 was previously declared with a different type.
 217
Author: user119017,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-05 12:13:32

Dodaję tu aktualną odpowiedź, biorąc pod uwagę ostatnie wydarzenia.

Możesz zadeklarować enum w C++11, o ile zadeklarujesz jednocześnie jego typ pamięci. Składnia wygląda tak:

enum E : short;
void foo(E e);

....

enum E : short
{
    VALUE_1,
    VALUE_2,
    ....
}

W rzeczywistości, jeśli funkcja nigdy nie odwołuje się do wartości wyliczenia, nie potrzebujesz w tym momencie pełnej deklaracji.

Jest to obsługiwane przez G++ 4.6 i nowsze (-std=c++0x lub -std=c++11 w nowszych wersjach). Visual C++ 2013 obsługuje to; w wcześniejsze wersje ma jakieś niestandardowe wsparcie, którego jeszcze nie rozgryzłem - znalazłem pewną sugestię, że prosta deklaracja forward jest legalna, ale YMMV.

 87
Author: Tom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-04 05:13:51

Forward deklarowanie rzeczy w C++ jest bardzo przydatne, ponieważ znacznie przyspiesza czas kompilacji. W C++ możesz zadeklarować kilka rzeczy, w tym: struct, class, function, itd...

Ale czy można forward zadeklarować enum w C++?

Nie możesz.]}

Ale dlaczego na to nie pozwolić? Jeśli jest to dozwolone, możesz zdefiniować swój typ enum w pliku nagłówkowym, a wartości enum w pliku źródłowym. Wygląda na to, że powinno być dozwolone prawda?

Źle.

W C++ nie ma domyślnego typu enum, tak jak w C #(int). W C++ Twój typ enum będzie określony przez kompilator jako dowolny typ, który będzie pasował do zakresu wartości, które masz dla twojego enum.

Co to znaczy?

Oznacza to, że podstawowy typ enum nie może być w pełni określony, dopóki nie zdefiniujesz wszystkich wartości enum. Których nie można oddzielić deklaracji i definicji swojego enum. Oraz w związku z tym nie można forward zadeklarować enum W C++.

Norma ISO C++ S7. 2. 5:

Podstawowy typ wyliczenia jest typem całkowym, który może reprezentować wszystkie wartości wyliczenia zdefiniowane w wyliczeniu. Jest to implementacja zdefiniowana, który typ całkowy jest używany jako typ bazowy dla wyliczenia, z wyjątkiem tego, że typ bazowy nie może być większy niż int, chyba że wartość wyliczenia nie może zmieścić się w int lub unsigned int. Jeśli enumerator-lista jest pusta, typ bazowy jest tak, jakby wyliczenie miało pojedynczy enumerator o wartości 0. Wartość sizeof() zastosowana do typu wyliczenia, obiektu typu wyliczenia lub enumeratora jest wartością sizeof() zastosowaną do typu bazowego.

Możesz określić rozmiar wyliczonego typu W C++ za pomocą operatora sizeof. Rozmiar wyliczonego typu jest rozmiarem jego podstawowego typu. W ten sposób możesz odgadnąć, jakiego typu jest Twój kompilator korzystanie z enum.

Co jeśli podasz typ swojego enum wprost tak:

enum Color : char { Red=0, Green=1, Blue=2};
assert(sizeof Color == 1);

Czy możesz przekazać swoje enum?

Nie. Ale dlaczego nie?

Określenie typu enum nie jest w rzeczywistości częścią obecnego standardu C++. Jest to rozszerzenie VC++. Będzie jednak częścią C++0x.

Źródło

 30
Author: Brian R. Bondy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-19 06:01:43

[moja odpowiedź jest błędna, ale zostawiłem ją tutaj, ponieważ komentarze są przydatne].

Forward deklarowanie enum jest niestandardowe, ponieważ wskaźniki do różnych typów enum nie mają gwarancji, że będą tej samej wielkości. Kompilator może potrzebować zobaczyć definicję, aby wiedzieć, jakie wskaźniki wielkości mogą być używane z tym typem.

W praktyce, przynajmniej we wszystkich popularnych kompilatorach, wskaźniki do enum są zgodne. Forward declaration of enums jest dostarczany jako rozszerzenie języka przez Visual Na przykład C++.

 16
Author: James Hopkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-09 11:32:25

Rzeczywiście nie ma czegoś takiego jak forward declaration of enum. Ponieważ definicja enum nie zawiera żadnego kodu, który mógłby zależeć od innego kodu używającego enum, zwykle nie jest problemem całkowite zdefiniowanie enum podczas pierwszej deklaracji.

Jeśli Twoje enum jest używane tylko przez prywatne funkcje Członkowskie, możesz zaimplementować enkapsulację poprzez posiadanie samego enum jako prywatnego członka tej klasy. Enum musi być jeszcze w pełni zdefiniowane w punkcie deklaracji, czyli, w ramach definicji klasy. Nie jest to jednak większy problem, jak deklarowanie tam prywatnych funkcji Członkowskich, i nie jest to gorsze ujawnienie wewnętrznych implementacji niż to.

Jeśli potrzebujesz głębszego stopnia ukrycia szczegółów implementacji, możesz podzielić ją na abstrakcyjny interfejs, składający się tylko z czystych funkcji wirtualnych i konkretnej, całkowicie ukrytej klasy implementującej (dziedziczącej) interfejs. Tworzenie instancji klas może być obsługiwane przez fabrykę lub statyczna funkcja member interfejsu. W ten sposób nawet prawdziwa nazwa klasy, nie mówiąc już o jej prywatnych funkcjach, nie zostanie ujawniona.

 7
Author: Alexey Feldgendler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 12:03:40

Po prostu zauważam, że powodem w rzeczywistości jest, że rozmiar enum nie jest jeszcze znany po deklaracji forward. Well, you use forward declaration of a struct to be able to pass a pointer around or Referer to a object from a place that ' s refered to in the forward declared struct definition himself.

Forward deklarowanie wartości enum nie byłoby zbyt użyteczne, ponieważ chcielibyśmy być w stanie przekazać wartość enum by-value. Nie mogłeś nawet mieć na to wskaznika, bo ja ostatnio powiedziano, że niektóre platformy używają wskaźników o różnej wielkości dla char niż dla int lub long. Wszystko zależy więc od zawartości enum.

Obecny Standard C++ wyraźnie uniemożliwia wykonywanie czegoś takiego jak

enum X;

(w 7.1.5.3/1). Ale kolejny Standard C++ z powodu przyszłego roku pozwala na następujące, co przekonało mnie, że problem faktycznie ma związek z podstawowym typem:

enum X : int;

Jest znana jako "nieprzezroczysta" deklaracja enum. Możesz nawet użyć X przez wartość w poniższym kodzie. A jego wyliczenia można później zdefiniować w późniejszej redeklaracji wyliczenia. Zobacz 7.2 w bieżącym projekcie roboczym.

 6
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-26 15:54:43

Zrobiłbym to w ten sposób:

[w nagłówku publicznym]

typedef unsigned long E;

void Foo(E e);

[w nagłówku wewnętrznym]

enum Econtent { FUNCTIONALITY_NORMAL, FUNCTIONALITY_RESTRICTED, FUNCTIONALITY_FOR_PROJECT_X,
  FORCE_32BIT = 0xFFFFFFFF };

Dodając FORCE_32BIT zapewniamy, że Econtent kompiluje się do long, więc jest wymienny z E.

 4
Author: Laurie Cheers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 13:04:33

Jeśli naprawdę nie chcesz, aby Twoje enum pojawiło się w pliku nagłówkowym i upewniło się, że jest używane tylko przez prywatne metody, to jednym z rozwiązań może być zasada pimpl.

Jest to technika, która zapewnia ukrycie wewnętrznych elementów klasy w nagłówkach po prostu deklarując:

class A 
{
public:
    ...
private:
    void* pImpl;
};

Następnie w pliku implementacji (cpp) deklarujesz klasę, która będzie reprezentacją wewnętrznych.

class AImpl
{
public:
    AImpl(A* pThis): m_pThis(pThis) {}

    ... all private methods here ...
private:
    A* m_pThis;
};

Musisz dynamicznie utworzyć implementację w klasie konstruktor i usuń go w destruktorze, a przy implementacji metody publicznej musisz użyć:

((AImpl*)pImpl)->PrivateMethod();

Istnieją plusy używania pimpl, jednym z nich jest oddzielenie nagłówka klasy od jego implementacji, nie ma potrzeby przekompilowywania innych klas przy zmianie jednej implementacji klasy. Innym jest to, że przyspiesza czas kompilacji, ponieważ nagłówki są tak proste.

Ale jest to ból w użyciu, więc naprawdę powinieneś zadać sobie pytanie, czy samo deklarowanie swojego enum jako prywatnego w nagłówku jest tyle kłopotów.

 2
Author: Vincent Robert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 23:58:21

Można zawinąć enum w strukturę, dodając w niektórych konstruktorach i konwertacjach typów, a zamiast tego zadeklarować strukturę forward.

#define ENUM_CLASS(NAME, TYPE, VALUES...) \
struct NAME { \
    enum e { VALUES }; \
    explicit NAME(TYPE v) : val(v) {} \
    NAME(e v) : val(v) {} \
    operator e() const { return e(val); } \
    private:\
        TYPE val; \
}

To chyba działa: http://ideone.com/TYtP2

 2
Author: Leszek Swirski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-08 09:40:35

Wygląda na to, że nie można go zadeklarować w GCC!

Ciekawa dyskusja TUTAJ

 1
Author: prakash,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 11:37:29

Jest trochę niezgody, ponieważ to zostało wyrzucone (tak jakby), więc oto kilka istotnych bitów ze standardu. Badania pokazują, że standard tak naprawdę nie definiuje deklaracji forward, ani nie stwierdza wprost, że enums może być zadeklarowana lub nie może być zadeklarowana forward.

Po pierwsze, z dcl.enum, sekcja 7.2:

Podstawowy typ wyliczenia jest typem całkowym, który może reprezentować wszystkie wartości enumeratora zdefiniowane w wyliczenie. On implementacja-zdefiniowana, która integral typ jest używany jako typ podstawowy do wyliczenia, z wyjątkiem tego, że rodzaj bazowy nie może być większy niż int, chyba że wartość an enumerator nie może zmieścić się w int lub niepodpisana liczba całkowita. Jeśli enumerator-lista jest pusty, typ bazowy jest tak jakby wyliczenie miało jeden enumerator o wartości 0. Wartość sizeof () zastosowany do wyliczenia Typ, obiekt typu enumeracja, lub enumerator, jest wartością sizeof () Typ.

Więc podstawowy typ enum jest zdefiniowany w implementacji, z jednym niewielkim ograniczeniem.

Następnie przechodzimy do sekcji "Typy niekompletne" (3.9), która jest mniej więcej tak bliska standardowi w deklaracjach forward:

Klasa, która została zadeklarowana, ale nie zdefiniowana, lub tablica nieznanego rozmiaru lub niekompletny Typ elementu, jest niekompletnie zdefiniowanym typem obiektu.

Typ klasy (taki jak "class X") może być niekompletny w pewnym momencie tłumaczenia jednostkowe i kompletne później; Typ "klasa X" jest tym samym typem w obu punktach. Na deklarowany typ obiektu array może być tablicą niekompletnego typu klasy i dlatego niekompletne; jeżeli typ klasy zostanie uzupełniony później w jednostce tłumaczeniowej, typ tablicy staje się kompletny; typ tablicy w tych dwóch punktach jest tego samego typu. Deklarowany typ obiektu array może być tablicą o nieznanym rozmiarze i dlatego być niekompletne w jednym punkcie w jednostce translacyjnej i uzupełnione później; typy tablic na te dwa punkty ("array of unknown bound of T "i" array of N T") są różne typy. Typ wskaźnika do tablicy o nieznanym rozmiarze lub typu określonego przez typedef nie można wypełnić deklaracji jako tablicy o nieznanym rozmiarze.

Więc tam, standard dość dużo określa typy, które mogą być zadeklarowane forward. Enum nie było, więc autorzy kompilatorów ogólnie uważają forward za niedozwolone przez standard ze względu na zmienną wielkość jego podstawy Typ.

To też ma sens. Wartości enum są zwykle odniesione w sytuacjach wartości według, a kompilator rzeczywiście musi znać rozmiar pamięci w tych sytuacjach. Ponieważ rozmiar pamięci jest zdefiniowany w implementacji, wiele kompilatorów może po prostu wybrać 32-bitowe wartości dla bazowego typu każdego enum, w którym to momencie staje się możliwe zadeklarowanie ich dalej. Ciekawym eksperymentem może być próba zadeklarowania enum w visual studio, a następnie zmuszenie go do użycia bazowego wpisz greater than sizeof (int), jak wyjaśniono powyżej, aby zobaczyć, co się stanie.

 1
Author: Dan Olson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Dla VC, Oto test o deklaracji forward I określeniu typu bazowego:

  1. poniższy kod jest skompilowany ok.
    typedef int myint;
    enum T ;
    void foo(T * tp )
    {
        * tp = (T)0x12345678;
    }
    enum T : char
    {
        A
    };

Ale dostałem ostrzeżenie dla /W4 (/W3 nie ponosi tego ostrzeżenia)

Warning C4480: nonstandard extension used: specifying based type for enum ' T '

  1. VC (Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86) wygląda buggy w powyższym przypadku:

    • Gdy widzisz enum T; VC zakłada, że typ enum t używa domyślnych 4 bajtów int jako podstawowego typu, więc wygenerowany kod asemblera to:
    ?foo@@YAXPAW4T@@@Z PROC                 ; foo
    ; File e:\work\c_cpp\cpp_snippet.cpp
    ; Line 13
        push    ebp
        mov ebp, esp
    ; Line 14
        mov eax, DWORD PTR _tp$[ebp]
        mov DWORD PTR [eax], 305419896      ; 12345678H
    ; Line 15
        pop ebp
        ret 0
    ?foo@@YAXPAW4T@@@Z ENDP                 ; foo

Powyższy kod asemblera jest wyodrębniony z /Fatest.ASM bezpośrednio, nie moje osobiste przypuszczenie. Czy widzisz mov DWORD PTR [eax], 305419896 ; 12345678H linia?

Udowadnia to następujący fragment kodu:

    int main(int argc, char *argv)
    {
        union {
            char ca[4];
            T t;
        }a;
        a.ca[0] = a.ca[1] = a.[ca[2] = a.ca[3] = 1;
        foo( &a.t) ;
        printf("%#x, %#x, %#x, %#x\n",  a.ca[0], a.ca[1], a.ca[2], a.ca[3] );
        return 0;
    }

Wynik jest: 0x78, 0x56, 0x34, 0x12

  • po usunięciu deklaracji forward z enum T i przesunięciu definicji funkcja foo po definicji enum T: wynik jest OK:

Powyższa instrukcja klucza staje się:

MOV BYTE PTR [eax], 120; 00000078h

Ostateczny wynik to: 0x78, 0x1, 0x1, 0x1

Uwaga wartość nie jest nadpisywana

Dlatego używanie forward-declaration of enum w VC jest uważane za szkodliwe.

BTW, żeby się nie dziwić, składnia deklaracji typu bazowego jest taka sama jak jej w C#. W pratice odkryłem, że warto ocalić 3 bajty, określając bazowy Typ jako znak podczas rozmowy z wbudowanym systemem, który jest ograniczony pamięcią.

 1
Author: zhaorufei,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-04 19:15:45

W moich projektach zastosowałem technikę wyliczania przestrzeni nazw do radzenia sobie z enums ze starszych i zewnętrznych komponentów. Oto przykład:

Do przodu.h:

namespace type
{
    class legacy_type;
    typedef const legacy_type& type;
}

Enum.h:

// May be defined here or pulled in via #include.
namespace legacy
{
    enum evil { x , y, z };
}


namespace type
{
    using legacy::evil;

    class legacy_type
    {
    public:
        legacy_type(evil e)
            : e_(e)
        {}

        operator evil() const
        {
            return e_;
        }

    private:
        evil e_;
    };
}

Foo.h:

#include "forward.h"

class foo
{
public:
    void f(type::type t);
};

Foo.cc:

#include "foo.h"

#include <iostream>
#include "enum.h"

void foo::f(type::type t)
{
    switch (t)
    {
        case legacy::x:
            std::cout << "x" << std::endl;
            break;
        case legacy::y:
            std::cout << "y" << std::endl;
            break;
        case legacy::z:
            std::cout << "z" << std::endl;
            break;
        default:
            std::cout << "default" << std::endl;
    }
}

Main.cc:

#include "foo.h"
#include "enum.h"

int main()
{
    foo fu;
    fu.f(legacy::x);

    return 0;
}

Zauważ, że nagłówek foo.h nie musi nic wiedzieć o legacy::evil. Tylko pliki, które używają typu legacy legacy::evil (tutaj: main.cc) muszą zawierać enum.h.

 1
Author: mavam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-13 16:41:01

Moim rozwiązaniem Twojego problemu byłoby albo:

1-Użyj int zamiast enums: Zadeklaruj swoje ints w anonimowej przestrzeni nazw w pliku CPP (Nie w nagłówku):

namespace
{
   const int FUNCTIONALITY_NORMAL = 0 ;
   const int FUNCTIONALITY_RESTRICTED = 1 ;
   const int FUNCTIONALITY_FOR_PROJECT_X = 2 ;
}

Ponieważ twoje metody są prywatne, nikt nie będzie mieszać z danymi. Możesz nawet przejść dalej, aby przetestować, jeśli ktoś wyśle Ci nieprawidłowe dane:

namespace
{
   const int FUNCTIONALITY_begin = 0 ;
   const int FUNCTIONALITY_NORMAL = 0 ;
   const int FUNCTIONALITY_RESTRICTED = 1 ;
   const int FUNCTIONALITY_FOR_PROJECT_X = 2 ;
   const int FUNCTIONALITY_end = 3 ;

   bool isFunctionalityCorrect(int i)
   {
      return (i >= FUNCTIONALITY_begin) && (i < FUNCTIONALITY_end) ;
   }
}

2: Utwórz pełną klasę z ograniczonymi instancjami const, jak w Javie. Forward deklaruje klasę, A następnie definiuje ją w pliku CPP, a instancjuj tylko wartości podobne do enum. Zrobiłem coś takiego w C++, a wynik nie był tak satysfakcjonujący, jak pożądany, ponieważ potrzebował kodu do symulacji enum (konstrukcja kopii, operator =, itp.).

3: zgodnie z wcześniejszą propozycją, użyj zadeklarowanego prywatnie enum. Pomimo tego, że użytkownik zobaczy jego pełną definicję, nie będzie mógł z niej korzystać, ani korzystać z prywatnych metod. Tak więc zwykle będziesz mógł modyfikować enum i zawartość istniejących metod bez konieczności rekompilacji kodu używającego twojej klasy.

Myślę, że rozwiązanie 3 albo 1.
 0
Author: paercebal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 23:46:03

Dla każdego, kto ma do czynienia z tym dla iOS/Mac / Xcode,

Jeśli masz do czynienia z tym podczas integracji nagłówków C / C++ w XCode z Objective-C, po prostu zmień rozszerzenie pliku z. mm na .m

 0
Author: Pankaj Gaikar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-18 03:59:17

Ponieważ enum może mieć różną wielkość (kompilator decyduje o rozmiarze danego enum), wskaźnik do enum może również mieć różną wielkość, ponieważ jest typem integralnym(znaki mają różną wielkość na niektórych platformach na przykład).

Więc kompilator nie może nawet pozwolić ci zadeklarować enum i User wskaźnika do niego, ponieważ nawet tam, potrzebuje rozmiaru enum.

 -1
Author: Carl Seleborg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 11:41:55

Definiujesz wyliczenie, aby ograniczyć możliwe wartości elementów typu do ograniczonego zbioru. Ograniczenie to ma być egzekwowane w czasie kompilacji.

Deklarowanie przez forward faktu, że później użyjesz 'ograniczonego zestawu' nie dodaje żadnej wartości: kolejny kod musi znać możliwe wartości, aby z niego skorzystać.

Chociaż kompilator jest zaniepokojony rozmiarem typu wyliczeniowego, intencja wyliczenia zostaje utracona, gdy / align = "left" /

 -1
Author: xtofl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-27 13:05:06