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.
self.member = somethingand it creates a class member, then no, this is impossible. All members have to be defined within class definition.private: std::vector<Schema> arr;andDatabase(int tableCount = 100) : arr(static_cast<std::size_t>(tableCount)) {}sizeof(Database)cannot depend on the specific constructor used. AllDatabaseobjects have the same members and the same size. That's why you can ask about the class size.