2016-02-24 2 views
0

Disons que je veux créer une interface pourComment faire des classes de base héritées utilisent une variable commune

  1. Item s qui ont un contenu qui peut être lu.
  2. Item s qui ont un contenu qui peut être écrit.
  3. Item s qui ont un contenu qui peut être lu une/o écrite

Cependant, je ne veux pas créer 3 classes abstraites que je veux passer un Item, qui est en lecture accessible en écriture à une fonction qui accepte uniquement les éléments lisibles.

par exemple. vous ne pouvez lire qu'un Book, donc Book héritera de Readable, alors qu'un Note peut être lu et écrit, donc il héritera ReadWritable.

Alors maintenant, je peux créer la fonction comme ça:

std::string read(Readable& readable) const 

ou

void take_a_note(Writable& writable) 

J'ai cette Readable classe abstraite

template <typename ReadableType> 
class Readable 
{ 
public: 
    Readable(const ReadableType content); 
    virtual ~Readable(void); 
    virtual auto content(void) const noexcept -> const ReadableType&&; 

private: 
    const ReadableType _content; 
}; 

Et une classe abstraite Writable

template <typename WritableType> 
class Writable 
{ 
public: 
    Writable(void); 
    virtual ~Writable(void); 
    virtual void content(WritableType&& content) noexcept; 

private: 
    WritableType _content; 
}; 

Mais maintenant, je veux créer une classe abstraite qui combine les fonctionnalités, appelé ReadWritable

template <typename ReadWritableType> 
class ReadWritable: public Readable<ReadWritableType>, public Writable<ReadWritableType> 
{ 
public: 
    ReadWritable(ReadWritableType content); 
    virtual ~ReadWritable(void); 
    using Writable<ReadWritableType>::content; 
    using Readable<ReadWritableType>::content; 
}; 

C'est là le problème est, comme content(WritableType&& content) utilise Writable::_content, tandis que content(void) utilise Readable::_content. Comment puis-je les faire utiliser le même membre _content de données. Et si je peux le faire, y a-t-il un moyen de supprimer l'autre?


Ou mon approche complète est-elle incorrecte? Je suis ouvert à toutes les opinions.

+0

Je ne suis pas sûr d'avoir bien compris votre question - Mais avez-vous jeté un coup d'œil sur le concept de classe de base virtuelle? Cela garantirait qu'il n'y a qu'un seul membre _content dans votre classe ReadWritable dérivée. – tofro

+0

Je pensais que cela ne s'appliquait que si la classe de base était exactement la même base, par ex. si j'ai hérité de Readable deux fois. Le problème n'est pas vraiment qu'il y ait une surcharge, mais que Readable :: content() et Writable :: content() ont chacun leur propre variable privée '_content' et ne coordonnent pas – hgiesel

+2

Interface et implémentation séparées. L'interface ne doit stocker aucun état et vous devez stocker tous les états dans l'implémentation. –

Répondre

1

Je ne suis pas sûr d'avoir bien compris la question, mais d'après ce que je comprends, vous voulez que deux classes distinctes partagent les mêmes données et continuent à fonctionner avec ces données partagées.

J'ai testé avec plusieurs combinaisons et le code suivant fonctionne correctement. Cependant, je devais faire plusieurs changements:

#include <iostream> 

class ReadableType 
{ 
    public: int id=0; 
      int* sharedValue; 
}; 

class WritableType 
{ 
    public: int id=1; 
      int* sharedValue; 
}; 

class ReadWritableType 
{ 
    public: int id=2; 
      int* sharedValue; 
      ReadWritableType(int share){sharedValue = new int;*sharedValue = share;}; 
}; 

class Readable 
{ 
public: 
    void content(void){std::cout << "id: "<<_content->id <<" sharedValue: "<<*_content->sharedValue<<std::endl;}; 

protected: 
    ReadableType *_content; 
}; 


class Writable 
{ 
public: 
    void content(WritableType content){std::cout << "id: "<<_content->id <<" sharedValue: "<<*_content->sharedValue<<std::endl;}; 

protected: 
    WritableType *_content; 
}; 


class ReadWritable: public Readable, public Writable 
{ 
public: 
    ReadWritable(ReadWritableType* content); 
    using Writable::content; 
    using Readable::content; 
private: 
    void makeReadable(ReadWritableType* content); 
    void makeWritable(ReadWritableType* content); 
}; 

ReadWritable::ReadWritable(ReadWritableType* content) 
{ 
    makeReadable(content); 
    makeWritable(content); 
} 

void ReadWritable::makeReadable(ReadWritableType* content) 
{ 
    Readable::_content = new ReadableType(); 
    Readable::_content->sharedValue = content->sharedValue; 
} 

void ReadWritable::makeWritable(ReadWritableType* content) 
{ 
    Writable::_content = new WritableType(); 
    Writable::_content->sharedValue = content->sharedValue; 
} 
int main() 
{ 
    ReadWritable x(new ReadWritableType(5)); 
    WritableType s; 
    x.content(); 
    x.content(s); 
} 

La sortie est que chaque _content utilise une valeur privée (identifiant) et une valeur partagée (sharedValue) qui partage la même mémoire entre deux _contents.

1

Avec une couche supplémentaire, vous pouvez le faire

template <typename ReadableType> 
class IReadable 
{ 
public: 
    virtual ~IReadable() = default; 
    virtual const ReadableType& content() const noexcept = 0; 
}; 

template <typename WritableType> 
class IWritable 
{ 
public: 
    virtual ~IWritable(); 
    virtual void content(WritableType&& content) noexcept = 0; 
}; 

template <typename ReadableType> 
class Readable : public IReadable 
{ 
public: 
    Readable(const ReadableType& content); 
    virtual const ReadableType& content() const noexcept override; 
private: 
    const ReadableType _content; 
}; 

template <typename WritableType> 
class Writable 
{ 
public: 
    virtual void content(WritableType&& content) noexcept override; 
private: 
    WritableType _content; 
}; 

Et enfin:

template <typename ReadWritableType> 
class ReadWritable: public IReadable<ReadWritableType>, public IWritable<ReadWritableType> 
{ 
public: 
    ReadWritable(ReadWritableType content); 

    virtual void content(WritableType&& content) noexcept override; 
    virtual const ReadableType& content() const noexcept override; 
private: 
    ReadWritableType _content; 
}; 

Vous avez en effet réimplémenter ReadWritable::content, mais le code peut factoriser avec Readable/Writable une et réutilisée.