2010-09-24 5 views
1

J'apprécierais toute aide avec ceci.
J'ai un simple jeu de classes de classes de conteneur.
Il existe également une spécialisation permettant une implémentation différente lorsqu'un ensemble de données de datasets est instancié.Conteneur relationnel en C++ et problèmes de polymorphisme

Étant donné qu'un ensemble de données de datasets est un conteneur hétérogène, il existe une liste de classes abstraites de base qui doit déclarer une interface commune pour chaque dataset. Ce serait get(). Le problème est: Je ne peux pas spécifier un type de retour dans List :: get(), donc j'ai besoin de surcharger le retour void * dans les descendants.

Ive lire les restrictions suivantes: covariance

• La fonction B :: f renvoie une référence ou un pointeur vers une classe de type T, et A :: rendements f> d'un pointeur ou d'un référence à une classe de base directe ou indirecte non ambiguë de T.
• La qualification constante ou volatile du pointeur ou de la référence renvoyée par B :: f a la même valeur ou la même qualification volatile ou volatile du pointeur ou de la référence renvoyée par A :: F.
• Le type de retour de B :: f doit être complète au moment de la déclaration de B :: f, ou il peut être de type B.

http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=/com.ibm.xlcpp8a.doc/language/ref/cplr139.htm

Eh bien, rendre les objets contenus descendre de la même classe de base ne me sert à rien.
Alors, y a-t-il une solution à ce problème? Mieux encore: quelle est la bonne façon de faire ça en C++?

Dans le cas où vous vous demandez, ce que j'essaie de faire est un «conteneur relationnel», pour ainsi dire. Mais vous ne verrez pas la partie relationnelle dans le code ci-dessous de toute façon.
L'objectif est de stocker des données en gardant le conteneur inaperçu de toute relation entre liste. Ensuite, je voudrais stocker les relations dans une liste à part. Par exemple:

liste Personne
0 John
1 Arthur
2 Caroline

liste des voitures
0 - Ford
1 - Volkswagen
2 - Chrysler

Liste des relations
0 - 1; 2
1 - 0; 1
2 - 0; 2

à peu près comme une base de données relationnelle. En outre, j'ai des problèmes secondaires mineurs, comme la fabrication de set() pour accepter un maxsize nombre d'arguments. Impossible de réaliser cela avec va_list. Peut-être que je me suis précipité, de toute façon.

Point final: J'évite délibérément le STL pour apprendre, mais si une telle fonctionnalité existe déjà, j'aimerais savoir.

Merci beaucoup!

Le code ci-dessous:

#include <iostream> 
using namespace std; 

//--------------------------------------------------// 
// TRIVIAL DUMMY CLASSES 

class Person 
{ 
public: 
Person(char* n, unsigned int a): _name(n), _age(a){} 

char* name(){cout << "Im " << _name << endl; return _name;} 
unsigned int age(){cout << "Im " << _age << " years old." << endl; return _age;} 

private: 
char* _name; 
unsigned int _age; 
} p1("john", 28), p2("Arthur", 26), p3("Caoline", 31); 

class Car 
{ 
public: 
Car(char* m, unsigned int y): _model(m), _year(y){} 

char* model(){cout << "Its a " << _model << endl; return _model;} 
unsigned int year(){cout << "Im" << _year << " years old." << endl; return _year;} 

private: 
char* _model; 
unsigned int _year; 
} c1("Chrysler C-300", 1955), c2("Chrysler VH Charger", 1971), c3("Ford Fairlane", 1960); 
//--------------------------------------------------// 

class List 
{ 
public: 
List(): length(0){} 

// common interface so Lists of Lists can be created 
// can´t specify a return type so it returns void* 
// BUT need to override it in descendants. WHY IT DOESN´T WORK? 
virtual void* get(unsigned int i) = 0; 

protected: 
unsigned int length; 
}; 
//--------------------------------------------------// 

template <class C, unsigned int maxsize> 
class Dataset: public List 
{ 
public: 
Dataset() 
{ 
    // initialize pointers to null 
    for(int i = 0; i < maxsize; i++){ 
    data[i] = 0; 
    } 
}; 

// C* return type is ignored 
C* get(unsigned int i) 
{return data[i];}; 

int set(C* dataIn) 
{ 
    data[length] = dataIn; 
    return length++; 
}; 

protected: 
C* data[maxsize]; 
}; 

template <unsigned int maxsize> 
class Dataset <List, maxsize>: public List 
{ 
public: 
Dataset() 
{ 
    // initialize pointers to null 
    for(int i = 0; i < maxsize; i++){ 
    data[i] = 0; 
    } 
}; 

List* get(unsigned int i) 
{return data[i];}; 

int set(List* dataIn) 
{ 
    data[length] = dataIn; 
    return length++; 
}; 

protected: 
List* data[maxsize]; 
}; 
//--------------------------------------------------// 
int main() 
{ 
Dataset <Person, 3> columnPerson; 
// populate person list 
columnPerson.set(&p1); 
columnPerson.set(&p2); 
columnPerson.set(&p3); 

Dataset <Car, 3> columnCar; 
// populate car list 
columnCar.set(&c1); 
columnCar.set(&c2); 
columnCar.set(&c3); 


Dataset <List, 10> relations; // create a list of lists 
// populate it 
relations.set(&columnPerson); 
relations.set(&columnCar); 

// getting a void* and casting it 
Person* ptrPerson = (Person*) relations.get(0)->get(0); 
ptrPerson->name(); 

int i; 
cin >> i; 
}; 
+0

Pourquoi dites-vous fait l'objet contenu proviennent d'une base commune est d'aucune utilité pour vous? Voici comment vous atteindre vos objectifs. –

Répondre

0

Je ne vais pas essayer de répondre aux détails de mise en œuvre, mais vous pouvez, comme vous avez demandé, obtenir toutes les fonctionnalités de la bibliothèque boost.any. Il y a un tutoriel sur heterogenous containers en l'utilisant.

0

Lorsque vous remplacez une fonction virtuelle, tout doit être identique (paramètres, nom, type de retour). En outre, vous ne pouvez pas remplacer une fonction qui ne diffère que par type de retour (comme vous essayez de faire avec celui qui retourne C *.

Vous pourriez avoir à coller avec un vide * et de le jeter au bon type. De Bien sûr, vous aurez besoin de savoir quel type il est censé être. vous poussez l'enveloppe des conteneurs hétérogènes. En temps normal, ils doivent avoir une interface commune. Si vous voulez retourner différents types, vous ne disposez pas d'un interface commune.