I have a base_class which has no default constructor, and I'd like to define a vector version of it (called derived_class). I know I should initialize the base_class constructor in my derived_class constructor, but the code below which attempts to initialize a vector with size dim and base_class(0,1) in each row cannot be compiled (it complains error: constructor for 'derived_class' must explicitly initialize the base class 'base_class' which does not have a default constructor), unless I add a default constructor (the commented line) to base_class. Do I miss or misunderstand something? Is there a way to make it work without defining the default base_class constructor?
#include <iostream>
#include <vector>
class base_class
{
public:
//base_class(){};
base_class(double a, double b){a_=a; b_=b;}
private:
double a_, b_;
};
class derived_class : public base_class
{
public:
derived_class(int dim): vector_object(dim, base_class(0,1)){};
std::vector<base_class> print_vector_object() {return vector_object;}
private:
std::vector<base_class> vector_object;
};
int main()
{
int dim = 3;
derived_class abc(3);
std::cout << abc.print_vector_object().size() << std::endl;
return 0;
}
UPDATE: I understand that I can totally avoid inheritance here in this simple case, but please assume that I do need inheritance for actual practice, thanks.
UPDATE2: As hinted by #vishal, if the constructor of derived_class is written as
derived_class(int dim) : base_class(0,0), vector_object(dim, base_class(0,1)) {};
The code can pass compiler. But I still don't understand why I have to initialize in this way...
Well, since you do not want to create default constructor in base class, you can call base constructor by:
derived_class(double a, double b, int dim) : base_class(a,b), vector_object(dim, base_class(0,1)) {};
Your vector_object is a red herring and has nothing to do with the problem, as you can verify with the following piece of code which will also make the compiler complain about the missing base_class default constructor:
class derived_class : public base_class
{
public:
derived_class(int dim) {} // error, tries to use `base_class` default constructor,
// but there is none...
};
You must either provide a default constructor or use a non-default one. In every instance of derived_class, there is a base_class sub-object, and the sub-object has to be created somehow.
One possible source of misunderstanding is the fact that objects in an inheritance hierarchy are initialized from top to bottom (base to derived). It may not seem logical at first sight, but by the time the derived_class constructor runs, the base_class sub-object must already exist. If the compiler cannot provide for this, then you get an error.
So even though the derived_class constructor specifies how the base_class sub-object is created, the actual creation of the sub-object happens before the creation of the derived_class part.
You are asking the following:
shouldn't the base_class object be initialized in my code?
Your code must initialize it, but it does not. You don't initialize it anywhere, and the default initialization does not work because the base class does not have a default constructor.
Sometimes, it helps to consider inheritance a special form of composition (there are indeed some striking similarities). The following piece of code suffers from the same problem as the one in your posting:
class base_class
{
public:
//base_class(){};
base_class(double a, double b){a_=a; b_=b;}
private:
double a_, b_;
};
class derived_class // <--- no inheritance
{
public:
base_class my_base; // <--- member variable
derived_class(int dim) {};
};
Would you still think that derived_class initializes the base_class object?
Another possible source of misunderstanding is the aforementioned red herring. You are saying:
I just don't understand why I cannot initialize it in a vector (...).
Because the vector member variable has nothing to do with the base_class sub-object, or with the public base_class member variable in my other example. There is no magical relationship between a vector member variable and anything else.
Taking your original piece of code again, a complete derived_class object can be pictured as follows in memory:
+-------------------+
| +---------------+ |
| | double | | <--- `base_class` sub-object
| | double | |
| +---------------+ |
+-------------------+ +--------+--------+--------+....
| std::vector ---------------> | double | double | double |
+-------------------+ | double | double | double |
+--------+--------+--------+....
^
|
|
a lot of other
`base_class` objects
The base_class objects managed by the vector are completely unrelated to the base_class sub-object that owes its existence to class inheritance.
(The diagram is a little over-simplified, because a std::vector normally also stores some internal book-keeping data, but that's irrelevant to this discussion.)
However, your code does not make a convincing case for inheritance anyway. So why do you inherit in the first place? You may as well do like this:
#include <iostream>
#include <vector>
class base_class
{
public:
//base_class(){};
base_class(double a, double b){a_=a; b_=b;}
private:
double a_, b_;
};
class derived_class // <--- no more inheritance (and thus wrong class name)
{
public:
derived_class(int dim) : vector_object(dim, base_class(0,1)){};
std::vector<base_class> print_vector_object() {return vector_object;}
private:
std::vector<base_class> vector_object;
};
int main()
{
int dim = 3;
derived_class abc(3);
std::cout << abc.print_vector_object().size() << std::endl;
return 0;
}
Are you sure, that a derived_class-object is a base_class-object and holds a vector of base_class-objects?
I assume, you actually only want a vector of base_class-objects. If that is true, don't derive derived_class from base_class. Actually that is where your compiler message comes from. It tells you, that you'll have to initialize the base_class aspect of your derived_class-object.
So here is my solution for you (beware, code is untested and will probably contain some bugs):
#include <iostream>
#include <vector>
class base_class
{
public:
// c++11 allows you to explicitly delete the default constructor.
base_class() = delete;
base_class(double a, double b):
a_{a}, b_{b} // <- prefer initializers over constructor body
{};
private:
double a_;
double b_;
};
class derived_class // <- this name is wrong now of course; change it.
{
public:
derived_class(int dim):
// better initialize doubles with float syntax, not int.
vector_object{dim, base_class{0.0, 1.0}}
{};
// Note: this will copy the whole vector on return.
// are you sure, that is what you really want?
auto print_vector_object() -> std::vector<base_class> {
return vector_object;
};
private:
std::vector<base_class> vector_object;
};
int main(int, char**)
{
// int dim = 3; <- this is useless, you never use dim.
auto abc = derived_class{3};
std::cout << abc.print_vector_object().size() << std::endl;
return 0;
}
Note: my code is meant to be C++11.
I have rewritten your class slightly
#include <iostream>
#include <vector>
class base_class {
private:
double a_, b_;
public:
//base_class(){};
base_class(double a, double b ) : a_(a), b_(b) {}
virtual ~base_class();
};
class derived_class : public base_class {
private:
std::vector<base_class> vector_object;
public:
explicit derived_class( int dim ) : base_class( 0, 1 ) {
vector_object.push_back( static_cast<base_class>( *this ) );
}
~derived_class();
std::vector<base_class> get_vector_object() const { return vector_object; }
};
int main() {
int dim = 3;
derived_class abc(3);
std::cout << abc.get_vector_object().size() << std::endl;
return 0;
}
This builds and compiles correctly. There were a few changes I made: I used the constructors member initializer list where applicable, I've added a virtual destructor to your base class; any time you inherit from a base class should have a virtual destructor, I moved all private member variables to the top of the class instead of at the bottom, I prefixed the derived_class constructor with the explicit keyword since you only have 1 parameter passed into it, I've changed the derived_class constructor to use the base_class constructor within its member's initialization list and I populated its member variable vector within the constructor using the push_back() method and statically casting the dereferenced this pointer to a base_class type, and I've also changed your print_vector_object method to just get_vector_object since it doesn't print anything and only return the member vector from the class. I also declared this method as const so that it doesn't change the class since you are only retrieving it. The only question that I have is what does the int parameter in the derived_class do? It is not used in any place and you have no member variable to store it.
This section of your derived class here
public:
derived_class(int dim): vector_object(dim, base_class(0,1)){};
where you declare your constructor is not making any sense to me.
It appears that you are trying to use the member initialization list to populate your vector member variable by passing in your derived class's passed in parameter and calling the constructor to your base class with values of {0,1}. This will not work as you would expect. You first have to construct your Base Class object which is a sub object to this derived class than within your constructor's function scope you can then populate your member vector.
What you have will cause a problem because you do not have a default constructor supplied that is available to try and construct your derived type. Since from what I can gather on what you have shown and what it appears what you are trying to do it seems that you want to have the base_class initialized to {0,1} when the derived constructor is called; if this is the case you can just call your implemented constructor for the base_class with {0,1} passed in its constructor while your derived type tries to be constructed. This will allow the derived_class to be constructed properly since the base_class has been constructed. Now that you are able to begin construction of your derived type it looks like you want to save the constructed base_class into your derived types vector member variable. This is why I do this within the constructor and not within the initialization list and I push_back an instance of the derived type that is statically casted back to a base type using the dereferenced this pointer. Also when I set a break point in the main function where you are trying to print its size and I look at derived_class's member variable it is populated with 1 object that has the values of a = 0 and b = 1. To be able to print these you would have to add public get methods to return each variable. Also if the int parameter in your derived class is not needed you can remove it along with the explicit keyword. You could also implement a second constructor for the derived type that takes in two doubles just as the base does and pass those parameters from the derived_class constructor to the base_class constructor like this:
public:
derived_class( double a, double b ) : base_class( a, b ) {
vector_object.push_back( static_cast<base_class>( *this ) );
}
I will demonstrate a simple example of a base and two derived classes where the first instance will have to set the values upon construction while the second will have to use its own constructor where there is no default constructor that is defined in the base class.
class Base {
private:
double x_, y_, z_;
public:
Base( double x, double y, double z );
virtual ~Base();
};
Base::Base() :
x_( x ), y_( x ), z_( z ) {
}
Base::~Base() {
}
class DerivedA : public Base {
private:
int value_;
public:
explicit DerivedA( int value );
~DerivedA();
};
// In This Case A Must Set The Values In The Constructor Itself: I'll Just
// Set Them To (0, 0, 0) To Keep It Simple
DerivedA::DerivedA( int value ) :
Base( 0, 0, 0 ),
value_( value ) {
}
DerivedA::~DerivedA() {
}
class DerivedB : public Base {
private:
int value_;
public:
DerivedB( int value, double x, double y, double z );
~DerivedB();
};
// In This Case B Doesn't Have To Know What Is Needed To Construct Base
// Since Its Constructor Expects Values From Its Caller And They Can
// Be Passed Off To The Base Class Constructor
DerivedB::DerivedB( int value, double x, double y, double z ) :
Base( x, y, z ),
value_( value ) {
}
DerivedB::~DerivedB() {
}
Let me know if this helps you out!
Related
I am having an issue where I am trying to initialize an "array" in my constructor, which I have done before with this method and it worked fine, however this time the class I am trying to do this this to is using inheritance (not used this a lot so could be something easy). I am getting an error saying that "No default constructor exists for class "Control_Reg_Value_HV", but I have fully defined that class with all special member functions needed.
Below shows the parts of the code I feel are important. I know that if I make a constructor then the compiler wont generate any for me, but I thought that the Control_Reg_Value_HV class is or does have default constructors.
Any help with this would be great.
Thanks in advance.
class Control_Reg_Value_HV;
class Data_SPI;
class Control_Reg_Value_HV{
public:
//----------------Special Member functions-----------------
Control_Reg_Value_HV(uint16_t Control_Write_Value_, uint16_t Control_Store_Value_); //Constructor
Control_Reg_Value_HV(const Control_Reg_Value_HV& C); //Copy Constructor
Control_Reg_Value_HV& operator=(const Control_Reg_Value_HV& C); //Equals Function
~Control_Reg_Value_HV(){} // Destructor
//---------------------------------------------------------
// rest of class, get and sets etc
);
//---------------------------------------------------------
//special member function definitions here
//------------------------Constructor definitions-----------------------------------------
Control_Reg_Value_HV::Control_Reg_Value_HV(uint16_t Control_Write_Value_, uint16_t Control_Store_Value_ )
:Control_Write_Value(Control_Write_Value_),Control_Store_Value(Control_Store_Value_){}
//----------------------------------------------------------------------------------------
//class with inheritance - where the issue is
class Data_SPI:public: Control_Reg_Value_HV{
public:
//----------------Special Member functions-----------------
//static uint16_t position;
Data_SPI()
:Resistance_Val_HV{10,11}{} //how ever many values needed, Issue here
private:
uint16_t Resistance_Val_HV[200];
//---------------------------------------------------------
};
edit:
no default constructor exists for class "Control_Reg_Value_HV" C/C++(291)[Ln 93, Col 30
sorry I dont know how to put error messages in correct format here
edit 2: missed the public: from the inherited class
edit 3: added a constructor definition
Your problem is that your Data_SPI is also a Control_Reg_Value_HV, so when you try to construct a Data_SPI you both have to instantiate its members AND construct the underlying Control_Reg_Value_HV.
So either add a default constructor to Control_Reg_Value_HV, or explicitly add a call to the constructor with appropriate values:
Data_SPI()
:Control_Reg_Value_HV{ <insert arguments here> },
Resistance_Val_HV{10,11}{}
EDIT: **************
Hokay, an example:
class Base
{
public:
Base(int x, int y)
: _x{x}, _y{y}
{
}
private:
int _x;
int _y;
};
class Derived : public Base
{
public:
Derived() // Default contructor
: Base{0, 0}, // Call the constructor of Base with appropriate default values
_z{0} // Initialize the members of Derived with appropriate default values
{
}
Derived(int x, int y, int z) // Explicit constructor
: Base{x, y}, // Pass some of the arguments on to the Base constructor
_z{z} // Use the rest to initialize the members of Derived
{
}
private:
int _z;
};
I was learning about inheritance in C++. So whenever a object of a class is created a constructor is called.
And constructor is used to initialize the class variables.
#include<bits/stdc++.h>
using namespace std;
class Base
{
protected:
int x;
public:
Base(int a): x(a)
{
cout<<"Base"<<endl;
}
};
class Derived: public Base
{
private:
int y;
public:
Derived(int b):y(b)
{
cout<<"Derived"<<endl;
}
void print()
{
cout<<x<<" "<<y<<endl;
}
};
int main()
{
Derived d(20);
d.print();
return 0;
}
Since here I am creating object of base class and calling print function on this. So I should get output.
But my code is giving compiler error, why?
Can anyone help me understanding this?
When you construct your Derived object in the Derived(int b): y(b) {}, the Base part of this object has to be constructed too. Since you do provide a constructor for Base which takes an int there won't be an implicitly defined default constructor in the Base (even if it was, the int data member x would have an undefined value). Thus, there's no way to construct the d in the Derived d(20) using your definitions for both classes.
You may look toward the following approach:
// Inside Base class:
// We provide a default constructor
// As well as one that takes an int
Base(int a = 0): x(a) {}
// Inside Derived class:
// We supply a value for the Base and a value for the Derived part
Derived(int b, int d): Base(b), y(d) {}
// Inside main():
Derived d(20, 30);
d.print();
// Prints: 20 30
When we have a default constructor provided for the Base, we can even do like so, and it will compile:
// Base part will be default constructed
Derived(int b): y(b) {}
// ...Prints: 0 20
Here, the Base part of a Derived instance will have a default value, while the Derived part will have a value explicitly supplied to it. In general, this would probably be a mistake, of logical nature. Nevertheless, it will compile.
I was happy to find out that in C++11 we can inherit constructors like:
class Foo
{public:
Foo(int a, double b, std::string name, char somethingElse);
};
class Derived : public Foo
{public:
using Foo::Foo;
};
But I'm finding that I'm often extending the base class where there might be maybe one or two extra features, and I need to initialise a couple extra members by maybe passing as extra argument or something. In this case is seems I have to rewrite the constructor and pass all the arguments to the base one. I'm wondering if there is a better solution. I thought maybe just using the inherited constructor and then initialising the extra member on the next line after construction, but it doesn't seem right:
Derived d = Derived(6, 6.0, "name", 'a');
d.extraMember = 4;
d.funcptr = &somefunction;
I figured it was an excellent feature but then I realised more and more that my extended classes needed extra initialisation info.
Here's my example from my code:
struct Window
{
Window(Window* parent, vec2 position, vec2 size, const String& name);
};
struct ConsoleWindow : Window
{
using Window::Window;
// But I've had to rewrite the constructor again because in this constructor I do stuff like
//GUI::bIsConsoleWindowActive = true;
//GUI::unselectWindow();
//GUI::selectedWindow = this;
}
It seems to me you can't add extra things to the construction process without rewriting the constructor and calling the base and passing all the values. This is common throughout my classes.
If your base classes are copyable/moveable and not abstract, you can push the burden of constructing the base class onto the declaration of the derived object. Just accept a base object:
Derived(Base b, int extraMember) :
Base(std::move(b)), extraMember(extraMember)
{
}
Where the declaration becomes this
Derived d{Base{6, 6.0, "name", 'a'}, 4};
That isn't perfect either, since it places certain requirements on your base classes that may not hold. And if it looks like aggregate initialization to you, then that's because this sets out to mimic it.
I'm afraid the only way that can definitely be adapted to any situation, is to spell out a new c'tor like you do now.
It wasn't clear from your question if you are able to change the base class. Assuming you are, you might consider packaging up your base constructor arguments into a struct, which could be forwarded up from the derived constructor.
This is often seen when implementing the builder design pattern, which is one way to solve the telescoping constructor anti-pattern you're describing.
struct FooParts {
int i;
double d;
string s;
char c;
};
class Foo {
public:
Foo(FooParts const & parts) : parts(parts) {}
private:
FooParts parts;
};
class Derived : public Foo {
public:
Derived(FooParts const & parts, bool extra) : Base(parts), member(extra) {}
private:
bool member;
};
I'm not sure, from your question, if you realize that you can call the base constructor from your derived constructor. Using your example:
struct Window
{
Window(Window* parent, vec2 position, vec2 size, const String& name);
};
struct ConsoleWindow : Window
{
ConsoleWindow(Window* parent, vec2 position, vec2 size, const String& name, int otherValue)
: Window(parent, position, size, name)
{
// do something with `otherValue` here.
}
};
See for example here: calling the base class constructor in the derived class constructor
The most straightforward way to do what you described is to use the base class constructor in the initialization list of the derived class:
class Foo
{public:
Foo(int a, double b, std::string name, char somethingElse);
};
class Derived : public Foo
{
public:
Derived::Derived(int a, double b, std::string name, char somethingElse,
int _extraMember, char derivedSpecificThing) :
// Initialization list starts here
Foo(a, b, name, somethingElse),
extraMember(_extraMember)
{
// Do something with derivedSpecificThing etc.
}
private:
const int extraMember;
};
using Foo::Foo only exposes the constructor of the base class as an additional constructor for your derived class. Of course, the constructor of the base class cannot initialize the additional members of the derived class that it knows nothing about.
So, I have a Base class, and two Derived classes, let's call them Deriv1 and Deriv2.
Let's say Base class has lots of (protected or public) variables, which of course then are also included in Deriv1 and Deriv2.
Now let's say I have an instance of Deriv1. The billions of variables from the Base class are filled with individual values. Now I want to create a Deriv2 instance, using these shared values.
Now my question: How to copy over the Base class part of Deriv1 to Deriv2 without writing an assigment operator where I'd have to manually list all of the billions of Base class variables (and update it everytime I change something in the Base class)? Is there some way, be it dirty or not, to do this?
My initial idea was:
Deriv1 drv1;
... // actions regarding drv1, like changing variables
Base tempbase = drv1; // slicing off the non-base parts of Deriv1
Deriv2 drv2 = *dynamic_cast<Deriv2*>(&tempbase); // downcast
This did not work. It did compile (I had to add a virtual dummy function to Base for it), but during runtime, it said "access violation", so I guess dynamic_cast returned a null pointer. I tried using a reference instead pointer in the dynamic_cast, which also didn't work.
You could make use of the (implicitly defined) copy constructor of the base class, which copies all members (even private ones) by value (i.e. shallow copy). You could define an explicit copy constructor for the base class as well, but it seems not to be necessary in your case.
See the following example:
class A {
public:
A (int x, int y) : x(x), y(y) { };
// implicitly defined: A (const A &anA) : x(anA.x), y(anA.y) { }
private:
int x, y;
};
class B : public A {
public:
int z;
B(const A&anA) : A(anA) { }
B(const B&b, int z) : A(b), z(z) { }
};
class C : public A {
public:
int anythingElse;
C(const A&anA) : A(anA) { }
};
int main()
{
A a(10,20); // a.x = 10; a.y = 20
B b1(a); // b1.x = 10, b1.y = 20, b1.z = undefined.
B b2(b1,30); // b2.x = 10, b2.y = 20, b2.z = 30.
C c(b1); // c.x = 10; c.y = 20; c.anythingElse = undefined
return 0;
}
use of static_cast instead of dynamic_cast will solve this.
In C++, it's not possible to initialize array members in the initialization list, thus member objects should have default constructors and they should be properly initialized in the constructor. Is there any (reasonable) workaround for this apart from not using arrays?
[Anything that can be initialized using only the initialization list is in our application far preferable to using the constructor, as that data can be allocated and initialized by the compiler and linker, and every CPU clock cycle counts, even before main. However, it is not always possible to have a default constructor for every class, and besides, reinitializing the data again in the constructor rather defeats the purpose anyway.]
E.g. I'd like to have something like this (but this one doesn't work):
class OtherClass {
private:
int data;
public:
OtherClass(int i) : data(i) {}; // No default constructor!
};
class Foo {
private:
OtherClass inst[3]; // Array size fixed and known ahead of time.
public:
Foo(...)
: inst[0](0), inst[1](1), inst[2](2)
{};
};
The only workaround I'm aware of is the non-array one:
class Foo {
private:
OtherClass inst0;
OtherClass inst1;
OtherClass inst2;
OtherClass *inst[3];
public:
Foo(...)
: inst0(0), inst1(1), inst2(2) {
inst[0]=&inst0;
inst[1]=&inst1;
inst[2]=&inst2;
};
};
Edit: It should be stressed that OtherClass has no default constructor, and that it is very desirable to have the linker be able to allocate any memory needed (one or more static instances of Foo will be created), using the heap is essentially verboten. I've updated the examples above to highlight the first point.
One possible workaround is to avoid the compiler calling the OtherClass constructor at all, and to call it on your own using placement new to initialize it whichever way you need. Example:
class Foo
{
private:
char inst[3*sizeof(OtherClass)]; // Array size fixed. OtherClass has no default ctor.
// use Inst to access, not inst
OtherClass &Inst(int i) {return (OtherClass *)inst+i;}
const OtherClass &Inst(int i) const {return (const OtherClass *)inst+i;}
public:
Foo(...)
{
new (Inst(0)) OtherClass(...);
new (Inst(1)) OtherClass(...);
new (Inst(2)) OtherClass(...);
}
~Foo()
{
Inst(0)->~OtherClass();
Inst(1)->~OtherClass();
Inst(2)->~OtherClass();
}
};
To cater for possible alignment requirements of the OtherClass, you may need to use __declspec(align(x)) if working in VisualC++, or to use a type other than char like:
Type inst[3*(sizeof(OtherClass)+sizeof(Type)-1)/sizeof(Type)];
... where Type is int, double, long long, or whatever describes the alignment requirements.
What data members are in OtherClass? Will value-initialization be enough for that class?
If value-initialization is enough, then you can value-initialize an array in the member initialization list:
class A {
public:
A ()
: m_a() // All elements are value-initialized (which for int means zero'd)
{
}
private:
int m_a[3];
};
If your array element types are class types, then the default constructor will be called.
EDIT: Just to clarify the comment from Drealmer.
Where the element type is non-POD, then it should have an "accessible default constructor" (as was stated above). If the compiler cannot call the default constructor, then this solution will not work.
The following example, would not work with this approach:
class Elem {
public:
Elem (int); // User declared ctor stops generation of implicit default ctor
};
class A {
public:
A ()
: m_a () // Compile error: No default constructor
{}
private:
Elem m_a[10];
};
One method I typically use to make a class member "appear" to be on the stack (although actually stored on the heap):
class Foo {
private:
int const (&array)[3];
int const (&InitArray() const)[3] {
int (*const rval)[3] = new int[1][3];
(*rval)[0] = 2;
(*rval)[1] = 3;
(*rval)[2] = 5;
return *rval;
}
public:
explicit Foo() : array(InitArray()) { }
virtual ~Foo() { delete[] &array[0]; }
};To clients of your class, array appears to be of type "int const [3]". Combine this code with placement new and you can also truly initialize the values at your discretion using any constructor you desire. Hope this helps.
Array members are not initialized by default. So you could use a static helper function that does the initialization, and store the result of the helper function in a member.
#include "stdafx.h"
#include <algorithm>
#include <cassert>
class C {
public: // for the sake of demonstration...
typedef int t_is[4] ;
t_is is;
bool initialized;
C() : initialized( false )
{
}
C( int deflt )
: initialized( sf_bInit( is, deflt ) )
{}
static bool sf_bInit( t_is& av_is, const int i ){
std::fill( av_is, av_is + sizeof( av_is )/sizeof( av_is[0] ), i );
return true;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
C c(1), d;
assert( c.is[0] == 1 );
return 0;
}
Worth noting is that in the next standard, they're going to support array initializers.
Use inheritance for creating proxy object
class ProxyOtherClass : public OtherClass {
public:
ProxyOtherClass() : OtherClass(0) {}
};
class Foo {
private:
ProxyOtherClass inst[3]; // Array size fixed and known ahead of time.
public:
Foo(...) {}
};
And what about using array of pointers instead of array of objects?
For example:
class Foo {
private:
OtherClass *inst[3];
public:
Foo(...) {
inst[0]=new OtherClass(1);
inst[1]=new OtherClass(2);
inst[2]=new OtherClass(3);
};
~Foo() {
delete [] inst;
}
};
You say "Anything that can be initialized using only the initialization list is in our application far preferable to using the constructor, as that data can be allocated and initialized by the compiler and linker, and every CPU clock cycle counts".
So, don't use constructors. That is, don't use conventional "instances". Declare everything statically. When you need a new "instance", create a new static declaration, potentially outside of any classes. Use structs with public members if you have to. Use C if you have to.
You answered your own question. Constructors and destructors are only useful in environments with a lot of allocation and deallocation. What good is destruction if the goal is for as much data as possible to be allocated statically, and so what good is construction without destruction? To hell with both of them.