2013-02-28 11 views
10

porządku, w moim głównym mam:C++ wywołanie funkcji z wektorem wskaźników funkcji wewnątrz klasy, gdzie definicja funkcji jest w głównej

void somefunction(); 
int main() 
{ 
    //bla bla bla 
    SomeClass myclass = SomeClass(); 
    void(*pointerfunc)() = somefunction; 
    myclass.addThingy(pointerfunc); 

    //then later i do 
    myclass.actionWithDiffrentOutcomes(); 
} 

void somefunction() 
{ 
    //some code 
} 

aw klasie:

class SomeClass() 
{ 
    public: 
     void addThingy(void (*function)()); 
     void actionWithDiffrentOutcomes(); 
    private: 
     std::vector<void (**)()> vectoroffunctions; 
} 
SomeClass::addThingy(void (*function)()) 
{ 
    vectoroffunctions.push_back(&function); 
} 
SomeClass::actionWithDiffrentOutcomes() 
{ 
    (*vectoroffunctions[0])();; 
} 

Jestem w pewnym sensie nowy - to znaczy dla wskaźników, ale czytam ponad moje książki C++, googled, ext. i wydaje się to poprawne, kompiluje się, działa, ale kiedy nazywam "actionWithDiffrentOutcomes()", dostaję naruszenie zasad dostępu. Nie jestem pewien, co robić. wydaje się poprawne, ale coś jest oczywiście błędne. Jak więc wywołać funkcję z klasy, gdy definicja znajduje się w innej?

Robię to w ten sposób, ponieważ nie mogę zakodować każdej opcji w instrukcji switch.

+0

Twój przykładowy kod nie jest kompilowany; czy możesz dokładnie sprawdzić składnię i edytować pytanie? – congusbongus

+0

Ten kod nie zostanie skompilowany. Podaj krótki, samodzielny, poprawny (kompatybilny) przykład (http://sscce.org/). – Johnsyweb

Odpowiedz

12

Twój kod jest prawie poprawny. Twój wektor błędnie trzyma wskaźniki do wskaźników do funkcji, a nie tylko wskaźniki do funkcji. addThingy dodaje adres wskaźnika function do vector, ale ten wskaźnik wykracza poza zakres w następnym wierszu.

Zmień kod w następujący sposób:

//Store pointers to functions, rather than 
//pointers to pointers to functions 
std::vector<void (*)()> vectoroffunctions; 

SomeClass::addThingy(void (*function)()) 
{ 
    //Don't take the address of the address: 
    vectoroffunctions.push_back(function); 
} 

Ponadto, masz dużo błędów składniowych w pozostałej części kodu, który powinien zatrzymać kod z nawet kompilacji.

+0

Ach, dziękuję, to ma więcej sensu. Przykro mi z powodu składni, skopiowałem ją do np ++, aby opublikować ją tutaj, a następnie opublikować cały mój program. –

5

Problemem jest tutaj:

vectoroffunctions.push_back(&function); 

Ty dodanie adresu zmiennej lokalnej z . Lokalna zmienna zostanie zniszczona po powrocie z funkcji. Adres zapisany w wektorze wskazuje na zniszczony obiekt, dlatego w środowisku wykonawczym pojawia się błąd "naruszenie dostępu" pod numerem .

Aby rozwiązać ten problem, wykonaj następujące czynności:

Pierwsza zmiana to

std::vector<void (**)()> vectoroffunctions; 

do tego:

std::vector<void (*)()> _functions; //vector of function-pointer-type 
            //I changed the name also! 

który jest praktycznie taki sam jak:

std::vector<void()> _functions; //vector of function-type 

teraz zrobić to:

_functions.push_back(function); //add copy! 

Żeby było bardziej elastyczne, można użyć szablonu wraz z std::function jak:

class A 
{ 
    public: 
     template<typename Function> 
     void add(Function && fn) 
     { 
      _functions.push_back(std::forward<Function>(fn)); 
     } 
     void invoke_all() 
     { 
      for(auto && fn : _functions) 
       fn(); 
     } 
    private: 
     std::vector<std::function<void()>> _functions; 
}; 

teraz można używać do przechowywania funkcje, jak również funktory:

void myfunction() { std::cout << "myfunction" << std::endl ; } 

struct myfunctor 
{ 
     void operator()() { std::cout << "myfunctor" << std::endl ; } 
}; 

A a; 
a.add(myfunction); //add function 
a.add(myfunctor()); //add functor! 
a.invoke_all(); 

Wyjście (Online Demo):

myfunction 
myfunctor 

Nadzieję, że pomaga.

+0

Każde eleganckie rozwiązanie dla funkcji ze zmiennymi argumentami? –

+0

@ sid: Jaki jest przypadek użycia? – Nawaz

1

wskaźniki funkcyjne są znacznie bardziej czytelne z typedefs:

typedef void (*RequiredFunction)(); 

Następnie można zadeklarować addThingy() tak:

void addThingy(RequiredFunction function); 

I vectoroffunctions tak:

std::vector<RequiredFunction> vectoroffunctions; 

Definicja addThingy będzie:

void SomeClass::addThingy(RequiredFunction function) 
{ 
    vectoroffunctions.push_back(function); 
} 

A twój main() będzie wyglądać bardziej jak:

int main() 
{ 
    SomeClass sc; 
    RequiredFunction pointerfunc = somefunction; 
    sc.addThingy(pointerfunc); 
    sc.actionWithDiffrentOutcomes(); 
} 

znacznie mniej * s i & s, z którymi się popełniać błędy!

Powiązane problemy