I have defined an array within a class. I want to initialize the array with some values pre-decided value. If I could do it in definition only then it will be easier as I would have used
class A{
int array[7]={2,3,4,1,6,5,4};
}
But, I can't do that. This, I need to do inside Constructor. But I can't use the same above syntax as it would create a new array inside Constructor and won't affect the array defined in class. What can be the easiest way to do it?
class A{
public:
int array[7];
A::A(){
}
}
You can initialize the array in the constructor member initializer list
A::A() : array{2,3,4,1,6,5,4} {
}
or for older syntax
A::A() : array({2,3,4,1,6,5,4}) {
}
Your sample should compile, using a compiler supporting the latest standard though.
Also note your class declaration is missing a trailing semicolon
class A{
public:
int array[7];
A();
};
// ^
With C++11 you can write this:
class C
{
int x[4];
public:
C() : x{0,1,2,3}
{
// Ctor
}
};
Related
Consider I want to wrap some library code inside an object. That library needs to be set up and initialized by calling some function inside the constructor of that wrapper class.
The librarie's "objects" then diverge into creating more, different "objects" that the wrapper class wraps in form of yet another wrapper object that should be a plain member of that class.
But as far as I see it, members of classes can only be initialized or created by calling their constructor in the initalizer list of the constructor. The execution of these bits of code preceed the constructor of the actual class that does the initialization of the library and its environment, making it impossible for me to actually initialize that member object as a member and instead force me to initialize it as a pointer to the 2nd wrapper, because its constructor must be called manually within the first constructor's code.
Example:
class A {
public:
A() {
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
ptr_to_some_library_metadata *a = library_function(); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
//initialize b
}
private:
B b; //Wants to be a member but can not
};
class B {
B(ptr_to_some_library_metadata *a);
}
Member objects can only be constructed in the member initializer list. There are a few techniques which can be used to make it possible to initialize an object, though:
Use a helper [lambda] function doing the necessary extra work before return a suitable object. For example:
A()
: B([]{
if (!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
return library_function();
}()) {
}
You can delay construction by using a union with just the appropriate member. When using this technique the member needs to be explicitly destructed, for example:
class A {
union Bu { B b };
Bu b;
public:
A() {
if (!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
new(&b.b) B(library_function());
}
~A() {
b.b.~B();
}
// ...
};
I'd personally use the first approach. However, there are cases when using a union to delay construction is helpful.
Initializer lists are there to use another constructor than the default constructor.
But nothing impedes you for creating a custom function that will initialize b:
class A {
public:
A():b(init()) {
}
private:
B b; //Wants to be a member but can not
static B init()
{
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
ptr_to_some_library_metadata *a = library_function(); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
return B(a);
}
};
Wrap your library inside a class:
class LibraryWrapper
{
public:
LibraryWrapper()
{
if(!wrapped_library_init()) {
exit(CRITICAL_ERROR);
}
lib_data.reset(library_function()); /*Needs to
be called after wrapped_library_init() or needs a pointer to some
wrapped object created inside this constructor */
}
//~LibraryWrapper() {/**/}
//LibraryWrapper(const LibraryWrapper&) {/**/} // =delete; ?
//LibraryWrapper& operator=(const LibraryWrapper&) {/**/} // =delete; ?
//private: // and appropriate interface to hide internal
std::unique_ptr<ptr_to_some_library_metadata, CustomDeleter> lib_data;
};
class B {
public:
explicit B(ptr_to_some_library_metadata *a);
// ...
};
And use extra member or inheritance:
class A
{
public:
A() : b(lib.lib_data.get()) {}
private:
LibraryWrapper lib; // placed before B
B b;
};
I'm not used to c++ and I'm having a problem writing a constructor.
See this example, is a short version of the code I'm working on:
class B {
public:
B(int x);
}
class A {
public:
B b;
A(){
// here I have to initialize b
}
}
That throws a compiler error since I need to initialize b in A's constructor because B does not have a default constructor.
I think I have do it in the initialization list, but the B(int x) argument is a value I have to calculate with some algorithm, so I don't know how this should be properly done, or if I'm missing something or doing it wrong.
In other language like java I would have a reference to B and initialize it inside the A's constructor after the other code I need to get the value for the initialization.
What would be the right way to initialize b in this case?
Thanks!
You can invoke functions in your constructor initializer list
class B {
public:
B(int x);
}; // note semicolon
class A {
public:
B b;
A()
:b(calculateValue()) {
// here I have to initialize b
}
static int calculateValue() {
/* ... */
}
}; // note semicolon
Note that in the initializer list, the class is considered completely defined, so you can see members declared later on too. Also better not use non-static functions in the constructor initializer list, since not all members have yet been initialized at that point. A static member function call is fine.
You use an initializer list, something like this:
A() : b(f(x)) {}
#include<iostream>
class B {
public:
B(){} // A default constructor is a must, if you have other variations of constructor
B(int x){}
}; // class body ends with a semicolon
class A {
private:
B b;
public:
A(){
// here I have to initialize b
}
void write(){
std::cout<<"Awesome";
}
};
int main(){
A a;
a.write();
}
In C++, if you have a constructor that takes an argument, a default constructor is a must, unlike other languages as Java. That's all you need to change. Thanks.
How come, when setting up class composition, contained classes can be called with a default constructor but not with one that takes parameters?
That's kind of confusing; let me offer an example.
#include "A.h"
class B
{
private:
A legal; // this kind of composition is allowed
A illegal(2,2); // this kind is not.
};
Assuming both the default constructor and one that takes 2 integers exists, only one of these is allowed. Why is this?
It is allowed for sure, but you just need to write it differently. You need to use the initializer list for the composite class's constructor:
#include "A.h"
class B
{
private:
A legal; // this kind of composition is allowed
A illegal; // this kind is, too
public:
B();
};
B::B() :
legal(), // optional, because this is the default
illegal(2, 2) // now legal
{
}
You can provide constructor parameters, but you are initialising your members wrong.
#include "A.h"
class B
{
private:
int x = 3; // you can't do this, either
A a(2,2);
};
Here's your solution, the ctor-initializer:
#include "A.h"
class B
{
public:
B() : x(3), a(2,2) {};
private:
int x;
A a;
};
a class declaration does NOT initialize the members which compose the class. hence, the error when you are trying to constrcut an object inside the declaration.
member initialization takes place inside the constructor of a class. so you should write:
#include "A.h"
class B
{
public:
B();
private:
A a;
};
B::B() :
a(2,2)
{
}
Let's say that I have two classes A and B.
class A
{
private:
int value;
public:
A(int v)
{
value = v;
}
};
class B
{
private:
A value;
public:
B()
{
// Here's my problem
}
}
I guess it's something basic but I don't know how to call A's constructor.
Also the compiler demands a default constructor for class A. But if A has a default constructor than wouldn't the default constructor be called whenever I declare a variable of type A. Can I still call a constructor after the default constructor has been called? Or can I declare an instance of a class and then call a constructor later?
I think this could be solved using pointers but can that be avoided ?
I know that you can do something like this in C#.
EDIT: I want to do some computations in the constructor and than initialize the classes. I don't know the values beforehand.
Let's say I'm reading the value from a file and then I initialize A accordingly.
The term you are looking for is initializer list. It is separated from the constructor body with a colon and determines how the members are initialized. Always prefer initialization to assignment when possible.
class A
{
int value;
public:
A(int value) : value(value) {}
};
class B
{
A a;
public:
B(int value) : a(value) {}
}
I want to do some computations in the constructor and than initialize the classes. I don't know the values beforehand.
Simply perform the computation in a separate function which you then call in the initializer list.
class B
{
A a;
static int some_computation()
{
return 42;
}
public:
B() : a(some_computation()) {}
}
You use an initialization list to initialize the member variables.
public:
B() : value(4) { // calls A::A(4) for value.
}
Or can I declare an instance of a class and then call a constructor later?
Yes, you can do that. Instead of (A value;) declare (A* value;), and then B's constructor will be B():value(new A(5)){}.
In the B's destructor you will have to do delete value;
I think this could be solved using pointers but can that be avoided ?
Yes. Use shared_ptr.
Try:
B() :
value(0)
{
// Here's my problem
}
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.