-2

I'm implementing a toy SQL database. In my code I'd like to have an abstract class Field and its two derived classes IntField and StringField. Also I'd like to have a Tuple class which represents a tuple of fields. Of course, I need to have some container of fields in my Tuple class and this is what my code looks like at the moment:

// This is an abstract class, but the methods here are irrelevant
class Field {
  virtual Type GetType() = 0;
}

// This is a concrete implementation of Field
class IntField : Field {
  Type GetType() override { <some code> }
}

// This is another concrete impl of Field
class StringField: Field {
  Type GetType() override { <some code> }
}

// This class represents a tuple of Fields
class Tuple {
 private:
  std::vector<std::shared_ptr<Field>> fields;
 public:
  // Don't bother in this example that i can be out of range
  std::shared_ptr<Field> GetField(int i) { return fields[i]; }
  void SetField(int i, std::shared_ptr<Field> f) {
    fields[i] = f;
  }
}

I understand I cannot have a std::vector<Field> as Field class cannot be instantiated, thus I need to use smart pointers. What bothers me is the getting and setting of the fields are handled. Can this be done in some better way?

  • 1
    An 'abstract class' as in 'a class with an abstract (unimplemented) function'? Because neither one of the classes in your code bares that nature, which I believe is how abstract classes are defined. –  Oct 23 '22 at 16:40
  • What does "bothers me" mean? What does "better way" mean? Please be specific, and attempt to frame your question objectively, so that it can be answered with facts and citations. We do not allow opinion-oriented questions on Stackoverflow. – Sam Varshavchik Oct 23 '22 at 16:41
  • Yes, let me edit the post so it's clear – Franciszek Malinka Oct 23 '22 at 16:41
  • @SamVarshavchik I guess there are some guidelines and good practices on how to handle such cases and this is what I'm looking for. There are some known don't dos and I thought that I may be doing some here and there may be some more canonical way to do it. – Franciszek Malinka Oct 23 '22 at 16:45
  • Can you please elaborate and give us more details about your bothers. What exactly is bothering you? And why? – Some programmer dude Oct 23 '22 at 16:47
  • The problem here is that if you ask ten C++ developers what would be "some guidelines and good practices for doing " you are guaranteed to get at least fifteen different answers. There is no King Of C++ that hands down decrees, instructing His Royal Highness' subjects what is or isn't a "good practice". Please be specific as to what your question is. What does "bothers me" mean, and how do you define "better way". If you cannot explain what, specifically, is bothering you, or what "better way" means, how can you expect anyone to guess it, themselves? – Sam Varshavchik Oct 23 '22 at 16:47
  • I feel like handling access to the `fields` vector of the `Tuple` class via the `GetField` and `SetField` is tedious at the moment. Also I'm not sure if the implementation of these methods is correct. – Franciszek Malinka Oct 23 '22 at 16:51
  • 1
    If you're implement an sql db, this choice of design indeed seems a bit weird. After every table has a fixed set of data types that's the same for every entity. With your impementation you could have entirely different data types stored for every entry. Furhtermore this structure could easily result in memory fragmentation: for every `Tuple` there's the backing storage of the vector that's dynamically allocated, and one more dynamic memory allocation per column. Moreover all those atomic operations with the shared pointers certainly will have a negative impact on performance... – fabian Oct 23 '22 at 17:09
  • Again: what, specifically, is "tedious", and why do you have doubts about the correctness of the implementation? Does it compile? If it does, does it produce correct results? Please reframe your question in concrete, specific terms. Try to pretend that a complete stranger walked off the street. This stranger has no knowledge of what your program is trying to do. What is your ***specific*** question? – Sam Varshavchik Oct 23 '22 at 17:40
  • If you can't instantiate an abstract class, you can't put it into a vector. You can put *pointers to abstract class* inside a vector. – Thomas Matthews Oct 23 '22 at 17:48
  • What do you mean by 'better' in objective terms? – TylerH Oct 25 '22 at 16:34

1 Answers1

0

To answer the title of your question: you can't have a vector of an abstract class.

The std::vector requires that all entities be copyable or assignable. Since you can't instantiate an object of an abstract class, you can't have a vector of an abstract type.

However, you can have a vector of pointers to an abstract class.

Example:

std::vector<Field *> pointers_to_fields;
StringField sf;
IntField integer_field;
pointers_to_fields.push_back(&sf);
pointers_to_fields.push_back(&integer_field);
 
Thomas Matthews
  • 56,849
  • 17
  • 98
  • 154