473,322 Members | 1,719 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,322 software developers and data experts.

Mimicking Javas static class initializer in C++

Hi folks,

as the subject says, i'm a poor Java programmer trying to transfer some
of his wisdom into C++ world... here is what im trying to do this evening:

Java has a nifty feature called a static class initializer - something
like this:

public class Foo
{
private static Vector<Thingxx;
static
{
xx = new Vector<Thing>(42);
for (int i=0; i < xx.size(); ++i)
xx.set(i, new Thing());
}
}

where the static{} block is called once (when the class is first used),
thus suitable for complex initializations of static members.

Now i would like to have this in C++, can this be done?
Here is my current approach:

VPNChannel.h
------------

class VPNChannel
{
static const int MAX_CHANNELS = 4;

// Bitmask of allocated channels
static uint32_t smAllocated_channels_map;

//
// Vector holding all possible instances of VPNChannel
//
static VPNChannel *smInstances[MAX_CHANNELS];

//
// Static initializer
// This is kinda kludge to mimic Javas static {} class initializer
//
static uint32_t static_class_initializer();
}


VPNChannel.cpp
--------------

#include "VPNChannel.h"

uint32_t VPNChannel::smAllocated_channels_map(static_class_ initializer());

uint32_t VPNChannel::static_class_initializer()
{
for (int i=0; i < MAX_CHANNELS; ++i)
{
VPNChannel::smInstances[i] = (VPNChannel *)NULL;
}
return (uint32_t)0;
}

with this idea in mind:

static_class_initializer() is used to do complex initialization of an
static array, it returns a dummy zero value, so it can be used to
initialze another static variable (smAllocated_channels_map).
To my surprise, this compiles fine, but gives a linker error:

VPNChannel.o(.text+0x19):VPNChannel.cpp: undefined reference to
`VPNChannel::smInstances'
collect2: ld returned 1 exit status
(I'm using MinGW 3.4.2)

Any hint, what goes wrong here? Or maybe a better, more c++ish approach
to static initialization?

Cheers and Greetings
Andreas

Oct 27 '08 #1
11 5269
Andreas Wollschlaeger wrote:
as the subject says, i'm a poor Java programmer trying to transfer some
of his wisdom into C++ world... here is what im trying to do this evening:

Java has a nifty feature called a static class initializer - something
like this:

public class Foo
{
private static Vector<Thingxx;
static
{
xx = new Vector<Thing>(42);
for (int i=0; i < xx.size(); ++i)
xx.set(i, new Thing());
}
}

where the static{} block is called once (when the class is first used),
thus suitable for complex initializations of static members.

Now i would like to have this in C++, can this be done?
Here is my current approach:

VPNChannel.h
------------

class VPNChannel
{
static const int MAX_CHANNELS = 4;

// Bitmask of allocated channels
static uint32_t smAllocated_channels_map;

//
// Vector holding all possible instances of VPNChannel
//
static VPNChannel *smInstances[MAX_CHANNELS];

//
// Static initializer
// This is kinda kludge to mimic Javas static {} class initializer
//
static uint32_t static_class_initializer();
}


VPNChannel.cpp
--------------

#include "VPNChannel.h"

uint32_t VPNChannel::smAllocated_channels_map(static_class_ initializer());

uint32_t VPNChannel::static_class_initializer()
{
for (int i=0; i < MAX_CHANNELS; ++i)
{
VPNChannel::smInstances[i] = (VPNChannel *)NULL;
}
return (uint32_t)0;
}

with this idea in mind:

static_class_initializer() is used to do complex initialization of an
static array, it returns a dummy zero value, so it can be used to
initialze another static variable (smAllocated_channels_map).
To my surprise, this compiles fine, but gives a linker error:

VPNChannel.o(.text+0x19):VPNChannel.cpp: undefined reference to
`VPNChannel::smInstances'
collect2: ld returned 1 exit status
(I'm using MinGW 3.4.2)

Any hint, what goes wrong here? Or maybe a better, more c++ish approach
to static initialization?
------------------------------- Header:
class Foo
{
static vector<Thingxx;
public:
...
};

------------------------------- Implementation file:

vector<Thingyour_static_initialiser()
{
vector<Thingv(42);
for (int i = 0; i < 42; ++i)
v[i] = ...; // whatever specific you want to get

return v;
}

vector<ThingFoo::xx = your_static_initialiser();
....

(presuming you include all the relevant headers for 'vector', etc.)

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 27 '08 #2
Andreas Wollschlaeger schrieb:
Hi folks,

as the subject says, i'm a poor Java programmer trying to transfer some
of his wisdom into C++ world... here is what im trying to do this evening:

Java has a nifty feature called a static class initializer - something
like this:

public class Foo
{
private static Vector<Thingxx;
static
{
xx = new Vector<Thing>(42);
for (int i=0; i < xx.size(); ++i)
xx.set(i, new Thing());
}
}

where the static{} block is called once (when the class is first used),
thus suitable for complex initializations of static members.

Now i would like to have this in C++, can this be done?
Here is my current approach:

VPNChannel.h
------------

class VPNChannel
{
static const int MAX_CHANNELS = 4;

// Bitmask of allocated channels
static uint32_t smAllocated_channels_map;

//
// Vector holding all possible instances of VPNChannel
//
static VPNChannel *smInstances[MAX_CHANNELS];

//
// Static initializer
// This is kinda kludge to mimic Javas static {} class initializer
//
static uint32_t static_class_initializer();
}


VPNChannel.cpp
--------------

#include "VPNChannel.h"

uint32_t VPNChannel::smAllocated_channels_map(static_class_ initializer());

uint32_t VPNChannel::static_class_initializer()
{
for (int i=0; i < MAX_CHANNELS; ++i)
{
VPNChannel::smInstances[i] = (VPNChannel *)NULL;
}
return (uint32_t)0;
}

with this idea in mind:

static_class_initializer() is used to do complex initialization of an
static array, it returns a dummy zero value, so it can be used to
initialze another static variable (smAllocated_channels_map).
To my surprise, this compiles fine, but gives a linker error:

VPNChannel.o(.text+0x19):VPNChannel.cpp: undefined reference to
`VPNChannel::smInstances'
collect2: ld returned 1 exit status
(I'm using MinGW 3.4.2)

Any hint, what goes wrong here? Or maybe a better, more c++ish approach
to static initialization?

Cheers and Greetings
Andreas
You do not need to allocate every object with new in C++, so if you only
need a vector of Thing, use xx. If you need to allocate Thing on the
heap, use yy;
xx.h:

#include <vector>

class Thing
{
};

class Foo
{
private:
static std::vector<Thingxx;
static class MyVector : public std::vector<Thing*>{ public:
MyVector(); } yy;
};
xx.cpp:

#include <xx.h>

std::vector<ThingFoo::xx( 42 );
Foo::MyVector::MyVector()
{
for( int i = 0; i<42; ++i ) {
yy.push_back( new Thing() );
}
}

Foo::MyVector Foo::yy;

Lars
Oct 27 '08 #3
Lars Tetzlaff schrieb:
xx.cpp:

#include <xx.h>

std::vector<ThingFoo::xx( 42 );
Foo::MyVector::MyVector()
{
for( int i = 0; i<42; ++i ) {
yy.push_back( new Thing() );
}
}

Foo::MyVector Foo::yy;

Lars
Should be

push_back( new Thing() );

instead of

yy.push_back( new Thing() );
Lars
Oct 27 '08 #4
Andreas Wollschlaeger wrote:
Now i would like to have this in C++, can this be done?
One possible approach is to wrap the static data, which must be
initialized with code, inside a class/struct:

class Foo
{
struct XX
{
std::vector<Thingxx;

XX()
{
// Initialize 'xx' here.
// (You could also implement this in the compilation unit
// to reduce clutter in the header file.)
}
};

static XX xx;
};
Then in the compilation unit you define the XX instance:

Foo::XX Foo::xx; // Will be initialized with the XX constructor

Of course you'll have to access the vector with "xx.xx" from now on.
With a logical and modular naming scheme you can make it less ugly.
Oct 27 '08 #5
Lars Tetzlaff schrieb:
Andreas Wollschlaeger schrieb:
>Hi folks,

as the subject says, i'm a poor Java programmer trying to transfer some
of his wisdom into C++ world... here is what im trying to do this evening:

Java has a nifty feature called a static class initializer - something
like this:
You do not need to allocate every object with new in C++, so if you only
need a vector of Thing, use xx. If you need to allocate Thing on the
heap, use yy;
xx.h:

#include <vector>

class Thing
{
};

class Foo
{
private:
static std::vector<Thingxx;
static class MyVector : public std::vector<Thing*>{ public:
MyVector(); } yy;
};
xx.cpp:

#include <xx.h>

std::vector<ThingFoo::xx( 42 );
Foo::MyVector::MyVector()
{
for( int i = 0; i<42; ++i ) {
yy.push_back( new Thing() );
}
}

Foo::MyVector Foo::yy;
Well, great, this was just what i have been looking for: encapsulating
the statics initialization in some inner class and its default
constructor - much more elegant and "cplusplusish" than my previous
attempt :-) Tx to you and the other folks, added me some more insight to
C++ this evening!

Cheers
Andreas

Oct 27 '08 #6
Andreas Wollschlaeger wrote:
Lars Tetzlaff schrieb:
>Andreas Wollschlaeger schrieb:
>>Hi folks,

as the subject says, i'm a poor Java programmer trying to transfer some
of his wisdom into C++ world... here is what im trying to do this
evening:

Java has a nifty feature called a static class initializer - something
like this:
You do not need to allocate every object with new in C++, so if you only
need a vector of Thing, use xx. If you need to allocate Thing on the
heap, use yy;
xx.h:

#include <vector>

class Thing
{
};

class Foo
{
private:
static std::vector<Thingxx;
static class MyVector : public std::vector<Thing*>{ public:
MyVector(); } yy;
};
xx.cpp:

#include <xx.h>

std::vector<ThingFoo::xx( 42 );
Foo::MyVector::MyVector()
{
for( int i = 0; i<42; ++i ) {
yy.push_back( new Thing() );
}
}

Foo::MyVector Foo::yy;

Well, great, this was just what i have been looking for: encapsulating
the statics initialization in some inner class and its default
constructor - much more elegant and "cplusplusish" than my previous
attempt :-) Tx to you and the other folks, added me some more insight to
C++ this evening!
I can see why that solution would look nice to a Java developer, but in
general, it's a bad idea to derive your own classes from the standard
ones; it is especially non-c++ish.

C++ methods aren't virtual by default; they're more like final methods
in Java. In particular, their destructors aren't virtual, so if ever an
instance of a derived type is deleted through a pointer to a base with a
non-virtual destructor, nasty things will happen. You're much better
off in this case with Victor or Juha's solutions, both of which are fine.

FWIW, most should-be-simple things aren't as complicated as this; there
are just a few "don't do thats" that you have to pick up when you get
started, and you happen to have gotten some mediocre advice (no offense,
Lars) right off the bat.
Oct 27 '08 #7
Jeff Schwab wrote:
Andreas Wollschlaeger wrote:
>Lars Tetzlaff schrieb:
>>>
xx.h:

#include <vector>

class Thing
{
};

class Foo
{
private:
static std::vector<Thingxx;
static class MyVector : public std::vector<Thing*>{ public:
MyVector(); } yy;
};
xx.cpp:

#include <xx.h>

std::vector<ThingFoo::xx( 42 );
Foo::MyVector::MyVector()
{
for( int i = 0; i<42; ++i ) {
yy.push_back( new Thing() );
}
}

Foo::MyVector Foo::yy;

Well, great, this was just what i have been looking for: encapsulating
the statics initialization in some inner class and its default
constructor - much more elegant and "cplusplusish" than my previous
attempt :-) Tx to you and the other folks, added me some more insight
to C++ this evening!

I can see why that solution would look nice to a Java developer, but in
general, it's a bad idea to derive your own classes from the standard
ones; it is especially non-c++ish.
Unless you make the inheritance private, which would work equally well here:

static class MyVector : std::vector<Thing*>
{
public:
MyVector();
} yy;

--
Ian Collins
Oct 27 '08 #8
Ian Collins wrote:
Jeff Schwab wrote:
>Andreas Wollschlaeger wrote:
>>Lars Tetzlaff schrieb:
xx.h:

#include <vector>

class Thing
{
};

class Foo
{
private:
static std::vector<Thingxx;
static class MyVector : public std::vector<Thing*>{ public:
MyVector(); } yy;
};
xx.cpp:

#include <xx.h>

std::vector<ThingFoo::xx( 42 );
Foo::MyVector::MyVector()
{
for( int i = 0; i<42; ++i ) {
yy.push_back( new Thing() );
}
}

Foo::MyVector Foo::yy;
Well, great, this was just what i have been looking for: encapsulating
the statics initialization in some inner class and its default
constructor - much more elegant and "cplusplusish" than my previous
attempt :-) Tx to you and the other folks, added me some more insight
to C++ this evening!
I can see why that solution would look nice to a Java developer, but in
general, it's a bad idea to derive your own classes from the standard
ones; it is especially non-c++ish.
Unless you make the inheritance private, which would work equally well here:

static class MyVector : std::vector<Thing*>
{
public:
MyVector();
} yy;
True that. :)
Oct 27 '08 #9
Jeff Schwab schrieb:
Andreas Wollschlaeger wrote:
>Lars Tetzlaff schrieb:
>>Andreas Wollschlaeger schrieb:
Hi folks,

as the subject says, i'm a poor Java programmer trying to transfer some
of his wisdom into C++ world... here is what im trying to do this
evening:

Java has a nifty feature called a static class initializer - something
like this:
You do not need to allocate every object with new in C++, so if you only
need a vector of Thing, use xx. If you need to allocate Thing on the
heap, use yy;
xx.h:

#include <vector>

class Thing
{
};

class Foo
{
private:
static std::vector<Thingxx;
static class MyVector : public std::vector<Thing*>{ public:
MyVector(); } yy;
};
xx.cpp:

#include <xx.h>

std::vector<ThingFoo::xx( 42 );
Foo::MyVector::MyVector()
{
for( int i = 0; i<42; ++i ) {
yy.push_back( new Thing() );
}
}

Foo::MyVector Foo::yy;

Well, great, this was just what i have been looking for: encapsulating
the statics initialization in some inner class and its default
constructor - much more elegant and "cplusplusish" than my previous
attempt :-) Tx to you and the other folks, added me some more insight
to C++ this evening!

I can see why that solution would look nice to a Java developer, but in
general, it's a bad idea to derive your own classes from the standard
ones; it is especially non-c++ish.

C++ methods aren't virtual by default; they're more like final methods
in Java. In particular, their destructors aren't virtual, so if ever an
instance of a derived type is deleted through a pointer to a base with a
non-virtual destructor, nasty things will happen. You're much better
off in this case with Victor or Juha's solutions, both of which are fine.
Since the destruction of yy happens in the implementation file the type
is known to the compiler and the right destructor is called. The class
was ment *only* to initialize the static member. Generally I would agree
to your comment but not in the situation of initializing a static member
or a local variable.
>
FWIW, most should-be-simple things aren't as complicated as this; there
are just a few "don't do thats" that you have to pick up when you get
started, and you happen to have gotten some mediocre advice (no offense,
Lars) right off the bat.
Lars
Oct 28 '08 #10
In article <49***********************@newsspool2.arcor-online.net>,
Andreas Wollschlaeger <me************@arcor.dewrote:
Hi folks,

as the subject says, i'm a poor Java programmer trying to transfer some
of his wisdom into C++ world... here is what im trying to do this evening:

Java has a nifty feature called a static class initializer - something
like this:

public class Foo
{
private static Vector<Thingxx;
static
{
xx = new Vector<Thing>(42);
for (int i=0; i < xx.size(); ++i)
xx.set(i, new Thing());
}
}

where the static{} block is called once (when the class is first used),
thus suitable for complex initializations of static members.

Now i would like to have this in C++, can this be done?
Trying to make as literal a translation here. This will initialize things
the first time a Foo object is created; if no Foo is ever created, this
initialization will never run.

// Foo.hpp
class Foo {
public:
Foo();

private:
static vector<Thingxx;
}

// Foo.cpp
vector<ThingFoo::xx;

Foo::Foo()
{
if ( xx.empty() )
{
xx = new Vector<Thing>(42);
for (int i=0; i < xx.size(); ++i)
xx [o] = new Thing();
}
}

Here is a more general approach that separates the init code into its own
function:

// Foo.hpp
class Foo {
public:
Foo();

private:
static void first_use();
}

// Foo.cpp
void Foo::first_use()
{
// initialize statics
}

Foo::Foo()
{
static int call_once = (first_use(),0);
}

You could use a less-hacky approach to having first_use() called only
once, like a helper class, but this is a more concise approach.
Oct 29 '08 #11
In message <bl*************************@192.168.1.4>, blargg
<bl********@gishpuppy.comwrites
>In article <49***********************@newsspool2.arcor-online.net>,
Andreas Wollschlaeger <me************@arcor.dewrote:
>Hi folks,

as the subject says, i'm a poor Java programmer trying to transfer some
of his wisdom into C++ world... here is what im trying to do this evening:

Java has a nifty feature called a static class initializer - something
like this:

public class Foo
{
private static Vector<Thingxx;
static
{
xx = new Vector<Thing>(42);
for (int i=0; i < xx.size(); ++i)
xx.set(i, new Thing());
}
}

where the static{} block is called once (when the class is first used),
thus suitable for complex initializations of static members.

Now i would like to have this in C++, can this be done?

Trying to make as literal a translation here. This will initialize things
the first time a Foo object is created; if no Foo is ever created, this
initialization will never run.

// Foo.hpp
class Foo {
public:
Foo();

private:
static vector<Thingxx;
}

// Foo.cpp
vector<ThingFoo::xx;

Foo::Foo()
{
if ( xx.empty() )
{
xx = new Vector<Thing>(42);
???
xx is a vector, not a pointer.
for (int i=0; i < xx.size(); ++i)
xx [o] = new Thing();
.... and it contains Things, not pointers. You appear to be writing Java
here.
}
}

Here is a more general approach that separates the init code into its own
function:

// Foo.hpp
class Foo {
public:
Foo();

private:
static void first_use();
}

// Foo.cpp
void Foo::first_use()
{
// initialize statics
}

Foo::Foo()
{
static int call_once = (first_use(),0);
}

You could use a less-hacky approach to having first_use() called only
once, like a helper class, but this is a more concise approach.
--
Richard Herring
Oct 29 '08 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Qin Chen | last post by:
I will present very long code, hope someone will read it all, and teach me something like tom_usenet. This question comes to me when i read <<Think in C++>> 2nd, chapter 10 , name control,...
14
by: Mike Hewson | last post by:
Have been researching as to why: <example 1> class ABC { static const float some_float = 3.3f; }; <end example 1>
5
by: Tina | last post by:
I'm using C# 1.1.............. I add new Class item to my project. It's created as class Math I change it to public static class Math I get an error saying that "The modifier 'static' is...
12
by: Hemanth | last post by:
Hi, I have a base class with a static constructor and some abstract methods. Derived classes implement these methods. From articles on the web, it appears that there is no guarentee that this...
12
by: Philip Potter | last post by:
I'm reading the comp.lang.c++ faq and, though it is incredibly clear and lucid in many points, I am completely confused by question 29.6: ...
8
by: Per Bull Holmen | last post by:
Hey Im new to c++, so bear with me. I'm used to other OO languages, where it is possible to have class-level initialization functions, that initialize the CLASS rather than an instance of it....
6
by: Marvin Barley | last post by:
I have a class that throws exceptions in new initializer, and a static array of objects of this type. When something is wrong in initialization, CGI program crashes miserably. Debugging shows...
1
by: Sandro Bosio | last post by:
Hello everybody, my first message on this forum. I tried to solve my issue by reading other similar posts, but I didn't succeed. And forgive me if this mail is so long. I'm trying to achieve the...
15
by: akomiakov | last post by:
Is there a technical reason why one can't initialize a cost static non- integral data member in a class?
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.