Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] użycie różnych enum z różnych klas jako argument jednej funkcji zaprzyjaźnionej

Ostatnio zmodyfikowano 2018-02-07 10:17
Autor Wiadomość
marecki
Temat założony przez niniejszego użytkownika
[C++] użycie różnych enum z różnych klas jako argument jednej funkcji zaprzyjaźnionej
» 2018-02-06 09:10:05
Stworzyłem poniższy kod.
C/C++
#include <iostream>

using namespace std;

class klasa
{
public:
    enum typ { qq, ww, ee };
    int tt;
   
    friend void foo( klasa::typ sss );
};

class klasa2
{
public:
    enum typ { aa, ss, dd };
   
    friend void foo( klasa2::typ sss );
};


//klasa aa;

void foo( klasa::typ sss )
{
    cout << sss << endl;
}

void foo( klasa2::typ sss )
{
    cout << sss << endl;
}



int main()
{
    foo( klasa::ww );
    foo( klasa2::dd );
    return 0;
}


Wszystko działa ale chciałbym aby była zadeklarowana jedna funkcja foo, która mogła by przyjmować argument enum z dowolnej klasy, a nie jak powyżej zadeklarowane dwie funkcje dla każdej klasy osobno.
Proszę o sugestię jak można to wykonać.
P-169287
geceves
» 2018-02-06 09:22:35
Możesz poczytać o szablonach funkcji, jeżeli naprawdę uważasz, że chcesz tak operować.

Wewnątrz funkcji i tak będziesz próbował rozpoznać, który enum przychodzi a nie będziesz w stanie obsługiwać dwóch jednocześnie bo funkcja będzie znała albo jeden albo drugi.

Jak bardzo chcesz to zrobić to możesz rzutować na int i korzystać z offsetu dla rozróżnienia enumów ale to by było mocno niefajne.

Generalnie będzie lepiej jak powiesz, co próbujesz osiągnąć, bo aktualne rozwiązanie: szablony + enum + funkcje zaprzyjaźnione nie wygląda zbyt przyjemnie.
P-169288
marecki
Temat założony przez niniejszego użytkownika
» 2018-02-06 10:00:26
No właśnie nie chciał bym rozpoznawać w jednej funkcji który enum przychodzi. Chciałbym aby było to robione poprzez odpowiednie wstawienie argumentu.

Nie chcę tworzyć w plikach źródłowych dla klasy 'klasa' i ' klasa2' dwóch tak samo wyglądających funkcji które robiły by dokładnie to samo co mogła by zrobić jedna zadeklarowana w pliku nagłówkowym z deklaracjami klas.
P-169289
darko202
» 2018-02-06 12:02:42
1.
z
http://cpp0x.pl/kursy/Kurs-C++​/Typ-wyliczeniowy-enum/318
"
...
Dla każdego typu można utworzyć wskaźnik.
...
Można oczywiście utworzyć wskaźnik do enum:
...
"

2.
Example
z
http://en.cppreference.com/w​/cpp/language/enum

C/C++
//...

enum color {...}
//...

enum class altitude
    : char
{...}
//...

int main()
{
    color col = red;
    altitude a;
    a = altitude::low;
   
    std::cout << "col = " << col << '\n'
    << "a = " << a << '\n'
    << "f = " << f << '\n';
}

Output:
col = red
a = l
f = 3
P-169292
michal11
» 2018-02-06 15:46:53
Tak jak napisał geceves napisz co chcesz zrobić to dostaniesz lepsze odpowiedzi bo w zasadzie odpowiedź na pytanie "jak obsłużyć 2 rożne enumy w jednej funkcji?" już dostałeś, jedynie moge dodać, że możesz sobie napisać jedną funkcję jako implementację i wołać ją w dwóch innych które przyjmują te enumy
C/C++
enum E1 { };
enum E2 { };

namespace details
{
    void funImpl()
    {
    }
}

void fun1( E1 )
{
    funImpl();
}

void fun2( E2 )
{
    funImpl();
}
P-169294
marecki
Temat założony przez niniejszego użytkownika
» 2018-02-06 20:27:18
Wklejam kod pliku klasy.h

C/C++
#include <string>
#include <windows.h>

using namespace std;

typedef unsigned char byte;

const DWORD DEV1_MEM_LENGTH = 256;
const DWORD DEV2_MEM_LENGTH = 58;




// #######################################################################################################################
class DEVICE1
{
    // DANE, ARGUMENTY, KOMPONENTY KLASY, SK£ADOWE,
private:
    string name[ DEV1_MEM_LENGTH ];
    byte value[ DEV1_MEM_LENGTH ];
   
public:
    enum REG
    {
        reg1, reg2, reg3
       
    };
   
    // FUNKCJE, METODY, INTERFEJS KLASY, FUNKCJE SK£ADOWE,
public:
   
    void showRegister( REG reg );
   
};




// #######################################################################################################################
class DEVICE2
{
    // DANE, ARGUMENTY, KOMPONENTY KLASY, SKŁADOWE,
private:
    string name[ DEV2_MEM_LENGTH ];
    byte value[ DEV2_MEM_LENGTH ];
   
public:
    enum REG
    {
        reg1, reg2, reg3
    };
   
    // METODY,
public:
    void showRegister( REG reg );
   
};

Natomiast w plikach "DEVICE1.cpp" i "DEVICE2.cpp" jest definicja funkcji void showRegister(REG reg);

C/C++
void DEVICEx::showRegister( REG reg )
{
    char temp_tab[ 8 ] = { 0 }; // Tablica do której zapiszemy ciąg znaków,
    byte temp_value = value[ reg ]; // Zmienna tymczasowa do przechowania liczby
   
    for( int i = 0; i < 8; i++ )
    {
        temp_value = value[ reg ] &( 1 << i );
        if( temp_value > 0 )
             temp_tab[ i ] = '1';
        else
             temp_tab[ i ] = '0';
       
    }
   
    // WŁAŚCIWE WYŚWIETLANIE DANYCH,
    cout.width( 12 );
    cout << name[ reg ] << " = ";
    cout.width( 12 );
    cout <<( int ) value[ reg ];
    cout.width( 12 );
   
    for( int i = 7; i >= 0; i-- )
    {
        cout << temp_tab[ i ] << "   ";
    }
   
    cout << endl;
}

Nie chcę mieć definicji takiej samej funkcji w każdym pliku cpp i wywoływać ją jako 'showRegister(reg1);'. Chcę mieć jedną w pliku h i wywoływać ją w taki sam sposób.

Wykonałem pewną zamianę ale wtedy muszę funkcję wywoływać 'showRegister(value[reg1], name[reg1]);'

Próbowałem zrobić to z pomocą funkcji wirtualnej ale nie mogę ponieważ dostaję błędy w stylu 'value' was not declared in this scope
C/C++
class Device
{
public:
    void showRegister( REG reg )
    {
        char temp_tab[ 8 ] = { 0 }; // Tablica do której zapiszemy ciąg znaków,
        byte temp_value = value[ reg ]; // Zmienna tymczasowa do przechowania liczby
       
        for( int i = 0; i < 8; i++ )
        {
            temp_value = value[ reg ] &( 1 << i );
            if( temp_value > 0 )
                 temp_tab[ i ] = '1';
            else
                 temp_tab[ i ] = '0';
           
        }
       
        // WŁAŚCIWE WYŚWIETLANIE DANYCH,
        cout.width( 12 );
        cout << name[ reg ] << " = ";
        cout.width( 12 );
        cout <<( int ) value[ reg ];
        cout.width( 12 );
       
        for( int i = 7; i >= 0; i-- )
        {
            cout << temp_tab[ i ] << "   ";
        }
       
        cout << endl;
    }

Najlepiej jak by się dało tak zrobić że jako argument do funkcji przekazuję wskaźnik na obiekt oraz wartość REG z enum ale nie wiem jak to uczynić.
P-169298
Monika90
» 2018-02-06 22:26:43
No to sobie napisz szablon, a jeśli chcesz by miał dostęp do prywatnych składowych to go zaprzyjaźnij.
Np.
C/C++
#include <iostream>

using byte = unsigned char;

template < class Device, class Register >
void show( const Device & d, Register r )
{
    std::cout << d.names[ r ] << " = " << + d.registers[ r ] << std::endl;
}

class Device1
{
public:
    static constexpr int registers_count = 4;
    enum Register { r1, r2, r3, r4 };
    friend void show <>( const Device1 &, Register );
   
private:
    static constexpr const char * names[ registers_count ] = { "r1", "r2", "r3", "r4" };
    byte registers[ registers_count ] = { 11, 22, 33, 44 };
};

int main()
{
    Device1 d;
    show( d, d.r2 );
}

Nie wiem czy o to chodziło...
P-169299
Monika90
» 2018-02-06 22:52:19
Poza tym
C/C++
using namespace std;

typedef unsigned char byte;
Te dwie rzeczy na raz nie przejdą. W przestrzeni std jest zdefiniowany typ byte, więc będzie konflikt.
P-169300
« 1 » 2
  Strona 1 z 2 Następna strona