2016-06-16 52 views
5

È necessario avere una variabile di funzione all'interno della classe che abbia funzionalità di default e che la sua funzionalità possa essere sovrascritta. Esempio di come mi piaceva/voluto fare (purtroppo senza successo):Variabile di classe C++ std :: function che ha funzionalità predefinita e può essere modificabile

#include <iostream> 
#include <functional> 
using namespace std; 

class Base 
{ 
    public: 

    std::function<bool(void)> myFunc(){ 
    cout << "by default message this out and return true" << endl; 
    return true;} 
}; 

bool myAnotherFunc() 
{ 
cout << "Another functionality and returning false" << endl; 
return false; 
} 

int main() 
{ 
    Base b1; 
    b1.myFunc(); // Calls myFunc() with default functionality 
    Base b2; 
    b2.myFunc = myAnotherFunc; 
    b2.myFunc(); // Calls myFunc() with myAnotherFunc functionality 
    return 0; 
} 

lo so, questo codice non viene compilato. Qualcuno può aiutare a risolvere questo problema, o raccomandare qualcosa. Non è necessario essere std :: function, se esiste un altro modo per implementare questa logica. Forse dovresti usare lambda ?!

risposta

5

Passa a:

class Base { 
    public: 
    std::function<bool()> myFunc = [](){ 
    cout << "by default message this out and return true" << endl; 
    return true; 
    }; 
}; 

Live Demo

+0

noti che questo comporta quasi inevitabilmente in un comportamento indefinito una volta 'base' è posto in un file di intestazione, come '[]() {}' è usato in ogni compi costruttore sintetizzato dell'unità di ricerca e ha un ID di tipo diverso in diverse unità di compilazione. Ciò viola l'ODR per il costruttore. Per risolvere questo problema, dichiara 'Base();' nell'intestazione e 'Base :: Base() = default;' (o qualsiasi cosa) in * esattamente un * file cpp. Come spesso accade, molti compilatori non fanno cose orribili in questo caso di comportamento indefinito * in questo momento *, quindi passeranno inosservati. – Yakk

+0

Creat! c'è un altro problema. Aspetto codice: https://ideone.com/pO7oRZ classe derivata s.play() chiamerà Base :: myFunc(), che è comprensibile, perché myFunc() non è virtuale; C'è modo di fare in questo modo che questo play() non chiami Base :: myFunc(). Chiamerò son :: myFunc() – Samps

+0

@ user2440139 Dai un'occhiata a [demo] (http://coliru.stacked-crooked.com/a/29f789bd4273558a). – 101010

1

Soluzione con modifiche minime:

http://coliru.stacked-crooked.com/a/dbf33b4d7077e52b

class Base 
{ 
    public: 
    Base() : myFunc(std::bind(&Base::defAnotherFunc, this)){} 

    std::function<bool(void)> myFunc; 

    bool defAnotherFunc(){ 
    cout << "by default message this out and return true" << endl; 
    return true;} 
};