Mam klasę, która musi wywołać funkcje członków klasy szablonów B. Wyszukiwanie wokół Znalazłem ten przykładowy kod na tej stronie:

#include <iostream>

template<typename T, typename FType>
void bar(T& d, FType f) {
  (d.*f)(); // call member function
}

struct foible
{
  void say()
  {
    std::cout << "foible::say" << std::endl;
  }
};

int main(void)
{
  foible f;
  bar(f,  &foible::say); // types will be deduced automagically...
}

Pochodzi z tej odpowiedzi: Nazwa metody C ++ jako parametr szablonu

Ale nie robi 100% tego, czego potrzebuję. W jaki sposób powyższy kod zostanie ponownie napisany, aby:

  1. Metoda bar jest publicznym członkiem klasy, a nie samodzielnie funkcjonować
  2. argumenty d i f, które są przekazywane do metody {x2}} public członkowie tej samej klasy, do której bar jest członkiem, umożliwiając bar, aby mieć typ void (void)
  3. Typ obiektu foible to klasa, a nie struktura (opcjonalnie)?

[Edytuj 1] Moja własna próba przepisywania, która spotyka się do punktów 1) i 2), co jest nieprawidłowe:

#include <iostream>

template<class T, void (T::*FType)()>
class foo {
public:
  T obj;
  FType f;
void bar(void) {
  (obj.*f)(); // call member function
} // end bar
}; // end class foo

struct foible
{
  void say()
{
  std::cout << "foible::say" << std::endl;
}
};

int main(void)
{
foible f;
foo<foible, void (foible::*)()> c;
c.T = f;
c.Ftype = &foible::say;

c.bar(); // types will be deduced automagically...
}

Moim celem jest posiadanie obiektu typu klasy "A" przywołaj metody obiektu klasy typu klasy "b", tak że gdy te metody wykonywane obiekt typu "b" może użyć jego "tego" wskaźnika, aby odnieść się do swoich lokalnych danych . Chcę użyć wskaźników funkcyjnych Typ klasy "A", dzięki czemu jedynie muszą być określone tylko raz, a nie chcę, aby jedna klasa musi być pochodzi od innego.

2
Christopher Theriault 20 luty 2019, 19:52

2 odpowiedzi

Najlepsza odpowiedź

Rozwiązanie krok po kroku: Wszystkie przykłady wykorzystują następującą funkcję klasy i FOO

#include <iostream>
class A
{
public:
    void foo(){std::cout<<"foo"<<std::endl;}
};

Ta próbka działa bez szablonu: Wystarczy dzwonić do połączenia A :: Foo z wskaźnikiem do A i wskaźnik do A::foo:

class B
{
public:
    A *a;
    void (A::*p)(); 

    void bar()
    {
        (a->*p)(); //call A::foo 
    }
};
int main(void)
{
    A a;
    B b;
    b.a = &a;
    b.p = &A::foo;
    b.bar();
    return 0;
}

Następujący szablon dodany próbki class T, wskaźnik do metody foo pochodzącej z T.

template <class T>
class C
{
public:
    T* t;
    void (T::*p)(); 
    C(T &o) : t(&o){} 
    void bar()
    {
        (t->*p)();
    }
};
int main(void)
{
    A a;
    C<A> c(a);
    c.p = &A::foo;
    c.bar();
    return 0;
}

W poniższej, wskaźnik metody był również szablonowany, ale nie widzę, jak można go użyć, ponieważ powinieneś wiedzieć, ile argumentów, aby go dać, ale w każdym razie:

template <class T, typename F>
class D
{
public:
    T* t;
    F p; 
    D(T &o, F pf) : t(&o),p(pf){} 
    void bar()
    {
        (t->*p)();
    }
};
int main(void)
{
    A a;
    D<A, void (A::*)()> d(a, &A::foo);
    d.bar();
    return 0;
}
0
SHR 20 luty 2019, 18:19

Robisz to zbyt skomplikowane. Zapomnij o wskaźnikach do metod. Obecnie nie ma powodu, aby ich używać.

Po prostu zrobić coś takiego:

template<typename F>
void bar(F f) {
  doSomething();

  f(someArg);

  doSomething();
}

int main(void)
{
  foible f;
  bar([&f](auto x) { f.someMagicMethod(x); } );

  return 0;
}

Uwaga Takie podejście jest bardziej elastyczne i czytelne niż bawić się wskaźnikom metod.

1
R Sahu 20 luty 2019, 17:12