2009-12-08 3 views
3

Studer STL J'ai écrit un programme simple pour tester les foncteurs et les modificateurs. Ma question concerne la différence en utilisant CLASS ou STRUCT pour écrire un foncteur et essayer de l'utiliser avec des adaptateurs de fonction. Pour autant que je comprenne en C++ la différence entre CLASS et STRUCT est que dans le dernier cas les membres sont publics par défaut. C'est aussi ce que j'ai lu plusieurs fois dans les réponses sur ce site. Alors s'il vous plaît expliquez-moi pourquoi ce court morceau de code ne parviendra pas à compiler même si j'ai déclaré tous les membres (juste une fonction overloading()) public lorsque j'essaie d'utiliser le modificateur not2. (Je ne l'ai pas essayé d'autres modificateurs, par exemple liants encore)struct vs classe en tant que foncteur STL lors de l'utilisation de not2

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

template <class T> 
void print (T i) { 
    cout << " " << i; 
} 
// In the manual I read: 
// "In C++, a structure is the same as a class except that its members are public by default." 
// So if I declare all members public it should work.... 

template <class T> 
class mystruct : binary_function<T ,T ,bool> { 
    public : 
    bool operator() (T i,T j) const { return i<j; } 
}; 

template <class T> 
class generatore 
{ 
public: 
    generatore (T start = 0, T stp = 1) : current(start), step(stp) 
    { } 
    T operator()() { return current+=step; } 
private: 
    T current; 
    T step; 
}; 

int main() { 
    vector<int> first(10); 
    generate(first.begin(), first.end(), generatore<int>(10,10)); 
    first.resize(first.size()*2); 
    generate(first.begin()+first.size()/2, first.end(), generatore<int>(1,17)); 
    cout << "\nfirst :"; 
    for_each (first.begin(), first.end(), print<int>); 
    cout << "\nFORWARD SORT :"; 
    sort(first.begin(),first.end(),mystruct<int>());  // OK ! even with CLASS 
    for_each (first.begin(), first.end(), print<int>); 
    sort(first.begin(),first.end(),not2(mystruct<int>())); // <--- THIS LINE WILL NOT COMPILE IF I USE CLASS INSTEAD OF STRUCT 
    cout << "\nBACKWARD SORT :"; 
    for_each (first.begin(), first.end(), print<int>); 
    cout << endl; 
} 

Everithing fonctionne comme prévu si je l'utilise:

struct mystruct : binary_function<T ,T ,bool> { 
    public : 
    bool operator() (T i,T j) const { return i<j; } 
}; 

partie du message d'erreur que j'obtiens est:

g++ struct.cpp
/usr/include/c++/4.2.1/bits/stl_function.h:
In instantiation of ‘std::binary_negate >’:
struct.cpp:52: instantiated from here
/usr/include/c++/4.2.1/bits/stl_function.h:116:
error: ‘typedef int std::binary_function::first_argument_type’ is inaccessible
/usr/include/c++/4.2.1/bits/stl_function.h:338:
error: within this context
/usr/include/c++/4.2.1/bits/stl_function.h:119:
error: ‘typedef int std::binary_function::second_argument_type’ is inaccessible ....

Semble qu'au moins dans ce cas une structure n'est pas équivalente à une classe avec des membres publics, mais pourquoi?

Répondre

10

La différence que vous lisez d'autres réponses est correcte. struct est juste un class avec public accessibilité par défaut. Cela inclut le modificateur d'héritage . En gros, vous devez mentionner public avant le nom de la classe de base lorsque vous utilisez un class pour rendre ces définitions équivalentes:

template <class T> 
class mystruct : public binary_function<T ,T ,bool> { 
    public: 
    bool operator() (T i,T j) const { return i<j; } 
}; 

Sinon, le compilateur suppose que mystruct hérite en privé binary_function<T,T,bool>.

Vous pouvez vérifier ce fait en changeant la struct à:

struct mystruct : private binary_function<T ,T ,bool> { 
    public: // not required here 
    bool operator() (T i,T j) const { return i<j; } 
}; 

qui correspond à votre définition actuelle du class et voir le pleurnicher du compilateur avec un message d'erreur semblable.

+0

Ok! Maintenant ça marche. ! Merci ! – GBBL

2

Avec la structure de l'héritage est public par défaut avec classe, il est privé par défaut (si vous ne spécifiez pas public/privé/protégé)

Alors:

class mystruct : binary_function

signifie

class mystruct : private binary_function

mais

struct mystruct : binary_function

signifie

struct mystruct : public binary_function

Pour l'héritage privé mystruct peut utiliser tous les trucs publics de binary_function mais vous ne pouvez pas appeler la méthode publique de binary_function sur mystruct et mystruct n'est pas de binary_function Type (Je crois).

Alors, quand vous passez mystruct à l'endroit où binary_function devrait, mystruct ne définit pas des choses que l'on attend de binary_function.

Plus précisément, le foncteur devrait avoir les définitions suivantes qui sont fournis par binary_function, donc quand vous héritez de ce que vous avez déjà ces déclarations:

template <class _Arg1, class _Arg2, class _Result> 
struct binary_function { 
    typedef _Arg1 first_argument_type; ///< the type of the first argument (no surprises here) 
    typedef _Arg2 second_argument_type; ///< the type of the second argument 
    typedef _Result result_type;   ///< type of the return type 
}; 
Questions connexes