-2

We know that we can initialize defined parameters in class constructor. But i want to create an parameter in it.

Like this:

class Database{

public:
     Database(int tableCount = 100){
/* Here should create an array of class Schema with size of tableCount */
}

};
4
  • 4
    What do you mean by "create a parameter"? Please give as much information about what you're trying to achieve and why. At the moment, your question really isn't clear. Please see stackoverflow.com/help/how-to-ask for more guidance about asking questions here. Commented Apr 13 at 19:28
  • If you ask about mechanism like in Python, i.e. you write self.member = something and it creates a class member, then no, this is impossible. All members have to be defined within class definition. Commented Apr 13 at 19:35
  • private: std::vector<Schema> arr; and Database(int tableCount = 100) : arr(static_cast<std::size_t>(tableCount)) {} Commented Apr 13 at 19:42
  • Note that in C++, sizeof(Database) cannot depend on the specific constructor used. All Database objects have the same members and the same size. That's why you can ask about the class size. Commented Apr 14 at 12:38

2 Answers 2

2

All members of class must be defined in the class definition. The size of an array has to be known at compile time, so you can't actually use an array, but you can use std::vector and set its size in the constructor:

class Database {
public:
    Database(int table_count = 100) : table(table_count) {}
private:
    std::vector<Schema> table;
};
Sign up to request clarification or add additional context in comments.

Comments

0

Sure, you can create member objects at runtime. Just not the way you imagine.

#include <any>
#include <iomanip>
#include <iostream>
#include <string>
#include <unordered_map>


struct MyClass
{
  std::unordered_map <std::string, std::any> my;
  
  MyClass()
  {
    my["pi"]      = 3.14159265;
    my["name"]    = "John Jacob Jingleheimer Schmidt";
    my["word"]    = std::string{"gnarly"};
    my["integer"] = 42;
  }
};


int main()
{
  MyClass my_object;
  
  for (const auto & [name, value] : my_object.my)
  {
    std::cout << std::setw(8) << name << " --> ";
    
    // This is just to keep this post SHORT.
    // You should totally use the visitor pattern instead.
    // https://en.cppreference.com/w/cpp/utility/any/type
    try { std::cout << std::any_cast <const char *> (value) << "\n"; continue; } catch (...) { }
    try { std::cout << std::any_cast <std::string>  (value) << "\n"; continue; } catch (...) { }
    try { std::cout << std::any_cast <double>       (value) << "\n"; continue; } catch (...) { }
    std::cout << "<unhandled type: " << value.type().name() << ">\n";
  }

  my_object.my["world"] = "Earth";
  std::cout << std::any_cast <const char *> (my_object.my["world"]) << " is awesome.\n";
}

As you can see you can add and manipulate member objects at any time, both in the constructor and outside by users of your object.

Here I chose std::any as the discriminated type.
Another good choice is std::variant.
(Or even better, boost::variant — it’s less curmudgeonly than the std one.)

Again, whenever dealing with discriminated types, it is worth having a visitor pattern for dealing with operations on it. The code links to a nice basis for dealing with std::any, which would allow you to rewrite the main loop as something simple like:

  for (const auto & [name, value] : my_object.my)
  {
    std::cout << std::setw(8) << name << " --> " << print_any(value) << "\n";
  }

and the final line as:

  std::cout << print_any(my_object.my["world"]) << " is awesome.\n";

It works as expected.

(For those of you on Linux)

~/foo $ clang++ -Wall -Wextra -Werror -pedantic-errors -O3 -std=c++17 a.cpp

~/foo $ ./a.out
 integer --> <unhandled type: i>
    word --> gnarly
    name --> John Jacob Jingleheimer Schmidt
      pi --> 3.14159
Earth is awesome.

~/foo $ _

(For those of you on Windows)

C:/Users/Michael/foo> cl /EHsc /W4 /Ox /std:c++17 a.cpp
...

C:/Users/Michael/foo> a.exe
      pi --> 3.14159
    name --> John Jacob Jingleheimer Schmidt
 integer --> <unhandled type: int>
    word --> gnarly
Earth is awesome.

C:/Users/Michael/foo> _

As a final note, this is really not the way C++ was designed to be used. In general, your code should know what objects it has. The need to create unknown objects with unknown names at runtime is a really, truly rare one (if it actually exists).

In other words, there is surely a better way of accomplishing what you want than this.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.