2009-10-20 5 views
1

Je concevais une API publique en C++ et je crois que je souhaite conserver les conventions de style de fonction de propriété C++ qui ressemblent à int& Value() et const int& Value() const par opposition aux préfixes get/set qui return/assign by value car je sens que les patterns d'utilisation sont plus concis et également lisibles, tout en se fondant dans le code C++ existant très facilement.Les conventions de style de fonction de propriété étant affectées par void *

Je dois autoriser le programmeur à fournir ses propres métadonnées. J'ai choisi de le faire en exposant une fonction de propriété void*. Le problème est bien sûr que d'avoir des signatures comme:

class foo { 
    int& Value(); 
    const int& Value() const; 
    void* Metadata() 
    void* const Metadata() const 
}; 

... ne fonctionne pas parce que le suivant ne compilera pas:

void* ptr = ...; 
foo.Metadata() = ptr; 

À cause de cela, je dois utiliser quelque chose comme ce qui suit pour ce faire le travail:

class foo { 
    int& Value(); 
    const int& Value() const; 
    void* GetMetadata(); 
    void SetMetadata(void* const data); 
}; 

Mais cela rendrait les styles incohérents, donc pour l'instant j'ai choisi de coller avec des préfixes get/set tout au long de l'API entière à cause de cela, par exemple:

class foo { 
    int GetValue() const; 
    void SetValue(int value); 
    void* GetMetadata() const; 
    void SetMetadata(void* const data); 
}; 

Bien sûr, cela ne correspond pas à la convention de langage que je voudrais utiliser. Y a-t-il une approche alternative à tout cela? Si oui, qu'est-ce que c'est? Suis-je coincé avec les préfixes get/set?

Note: Je ne peux pas remplacer void* avec des modèles pour des méta-données utilisateur que l'API doit être aussi stable que possible.

En outre, j'ai déjà fourni une chaîne get/set paire non signé char* pour les chaînes utilisateur.

MISE À JOUR: Après quelques attention (re) considération que j'ai choisi de coller avec des préfixes get/set, je ne vais pas utiliser des références pour void* - si void* dégage une odeur, void*& est à peu près une décharge publique. En tant que tel, j'ai essentiellement opté pour quelque chose de similaire à ceci:

typedef void* Any; 

class foo { 
    ... 
    Any GetObject() const; 
    void SetObject(Any); 
    ... 
}; 

Merci pour votre participation. :)

+1

'void *' sont bruts. Pensez à utiliser autre chose, comme 'boost :: any', ou une classe de base abstraite. Que voulez-vous dire par méta-données, et quel est le plan global pour lequel vous l'utiliseriez? – GManNickG

+0

Je vais utiliser boost pour diverses choses dans l'implémentation, mais je ne veux pas exposer quoi que ce soit de boost lié à l'API publique. – Geoff

+0

Woops, aussi; méta-données est comme son nom décrit .. données sur les données. – Geoff

Répondre

3

Non pas que je suis sûr que ce soit la meilleure conception, mais, coller à la question suivante: Si, pour un attribut de type « int », vous écrivez:

int& Value(); //Used as setter 
int Value()const; //Used as getter 

faire la même chose pour un attribut de type "void *":

void*& Meta(); //Used as setter 
void* Meta()const; //Used as getter 
+0

Quelle partie du design n'aimes-tu pas? – Geoff

+2

Probablement la partie à ce sujet étant un «void *». Généralement, c'est un peu d'odeur de code. – greyfade

+0

En effet, et je suis d'accord, mais parfois il faut juste faire des compromis (voir les notes ajoutées au bas de ma question). – Geoff

2

Vous pourriez avoir vos Metadata fonctions renvoient des références aux pointeurs:

class foo { 
    int& Value(); 
    const int& Value() const; 
    void*& Metadata() 
    const void* const & Metadata() const 
}; 

Une autre alternative consiste à utiliser la surcharge:

class foo{ 
    int Value() const; 
    void Value(int); 
    void* Metadata() const; 
    void Metatdata(void*); 
}; 

Si vous allez dans cette voie, vous pouvez aussi faire les setters retourner l'ancienne valeur pour plus de commodité.

+0

Je suppose que vous devez utiliser un ancien compilateur qui ne supporte pas cela - cela fonctionne bien ici. – coppro

+0

semble que j'ai supprimé mon commentaire après l'avoir vu, heh. À tout prix; J'utilise MSVC 2008, et l'API sera multi-plateforme (gcc). Quelles étaient les définitions de fonctions de votre première classe foo? J'ai copié-collé le vôtre comme un exercice et je n'ai pas réussi à le compiler. – Geoff

+0

, mais le remplacement de void * par un typedef permet de compiler votre premier exemple (à l'exclusion du const redondant dans la seconde déclaration de métadonnées,/W4). – Geoff

Questions connexes