2012-02-25 16 views
6

Sono nuovo al C++ e sfortunatamente non riesco a smettere di pensare in C# (la mia lingua precedente). Ho letto alcuni libri, forum e il sito web di riferimento C++, ma non sono riuscito a trovare una risposta alla mia domanda, quindi ho pensato che potrei provare qui prima di arrendermi e scrivere qualcosa di brutto.C++ giusto modo di restituire una collezione generica di tipo

Ok, possiamo iniziare. Ho una classe con un metodo astratto succesorsFunction e mi piacerebbe che restituisse una raccolta di puntatori allo stato . Non voglio forzare gli implementatori a un contenitore specifico; Preferisco lasciarli scegliere (vettore, elenco, ecc.).

in modo che appaia in questo modo:

class Problem 
{ 
public: 
    virtual list<const State*>::iterator succesorsFunction(const State &state, list<const State*>::iterator result) const = 0; 
}; 

il problema qui è l'uso esplicito della lista. Come lo fai in C++?

ho pensato di usare i modelli, ma poi ho incontrato due problemi: 1) Sembra che non si può farlo con metodi astratti (o mi sbaglio) 2) Come faccio a dire il modello che dovrebbe contenere i puntatori? Stato?

+2

gamme di tipo-cancellati di Boost.Range può aiutare qui. – Xeo

+0

Puoi ampliare ciò che questa funzione dovrebbe raggiungere? Potrebbero esserci approcci alternativi. –

+2

Quindi ti piacerebbe restituire qualcosa di analogo a 'IEnumerable '? – svick

risposta

2

Non è possibile sovraccaricare i metodi basati sui tipi restituiti in C++.

Inoltre, "contenitori" in C++ non hanno la stessa base (come Collection in Java), quindi non è possibile restituire un contenitore generico.

Temo che non ci sia un modo pulito per farlo.

Scriverei solo overload (per parametro) o nomi di funzione diversi.

Per le vostre domande:

1) È possibile. Cosa ti fa pensare che non puoi?

2) Allo stesso modo dichiarato list: list<const State*> - const è facoltativo.

+4

Non penso che abbia detto nulla sull'overloading in base al valore di ritorno; ci sono più implementazioni con lo stesso tipo di ritorno. Vuole solo che il tipo di ritorno sia abbastanza generale da non limitare l'implementazione. –

+0

@ ErnestFriedman-Hill la sua domanda dice che vuole restituire una collezione e non vuole limitare la collezione (anche se il codice restituisce un iteratore). –

+0

... che non dice nulla sull'overloading in base al tipo restituito. –

0

Non si può avere un modello di funzione di membro che è virtuale, ma si può provare implementare amico funzione generica come questa:

template <typename yourType> 
yourType& succesorsFunction(const State &a, yourType &result){//Your return type can be without reference 
    //Your body 
    return result; 
} 

Se si chiama la funzione per esempio con vector<State> a argomento come questo:

processo di detrazione concluderà automaticamente che il tipo yourType è in realtà il tipo vector<State>, che a mio avviso risolve il problema. Inoltre, questa architettura ti aiuta a creare ad esempio il nuovo tipo di classe MyVector (che contiene gli array di States) e passare l'oggetto MyVector a succesorsFunction.

+0

Ho provato a farlo ma non ha funzionato con il metodo astratto. Potrei anche rimuovere il = 0 alla fine e farla finita con. Grazie per la tua risposta – wolfovercats

+0

@wolfovercats come compileresti il ​​risultato se non conosci il tipo? –

+0

@LuchianGrigore Conosco il tipo; è stato *. – wolfovercats

0

Se davvero si vuole rispettare l'utilizzo container STL, provare quanto segue:

template <template <typename, 
        typename = std::allocator<const State *> > class Container> 
Container<const State*> successorsFunction(const State &state, const Container<const State*> &c) const 
{ 
    // return something useful. 
} 

Se si insiste per avere questa funzione sia virtuale, allora non può essere un modello di funzione membro, basta sovraccaricarlo con i tipi che intendi supportare, quindi puoi renderli virtuali.

0

Questa è solo un'elaborazione della risposta C.T's. Si ricorda che se si restituisce un contenitore di puntatori, sarà necessario rilasciarli esplicitamente o utilizzare std::unique_ptr.
Solo un FYI .. come sei da C# sfondo.

È possibile utilizzare anche Stato o templatizzare.

template<typename Type, 
     template< typename, typename = std::allocator<Type*> > class Container 
     > 
Container<Type*> Successor(const Type& x) 
{ 
    Container<Type*> cont; 
    // something. 
    cont.push_back(new Type(x)); 
    return cont; 
} 

e lo chiamano

vector<State*> states = Successor<State, vector>(State(10)); 
Problemi correlati