473,396 Members | 1,784 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,396 software developers and data experts.

static class initialization functions in c++?

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. Like, for instance
the Objective-C method:

+(void)initialize

Which has the following characteristics: It is guaranteed to be run
before the first instance of that particular class is created. It is a
static member function, which otherwise operates the same way as any
other such functions: It can be overridden by subclasses, and the
overridden can call the superclass' implementation if needed, etc...

I have been looking, but not found an equivalent in c++. Is there one?

Per
Dec 25 '06 #1
8 8895

"Per Bull Holmen" <pb******@yahoo.comwrote in message
news:1h******************************@yahoo.com...
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.
In C++, only a object can be initialized. A class is not an object.
Like, for instance
the Objective-C method:

+(void)initialize

Which has the following characteristics: It is guaranteed to be run
before the first instance of that particular class is created.
A C++ class can contain static member objects, which are initialized
before 'main()' begins. If there is more than one static (member or
nonmember) object in the program, the order of their initialization
is not specified by the language.
>It is a
static member function,
In C++, only one member function of a class can initialize that
class's data members: the constructor.
which otherwise operates the same way as any
other such functions: It can be overridden by subclasses, and the
overridden can call the superclass' implementation if needed, etc...
A constructor can not be overridden. Creation of an object of a derived
type will automatically cause its base class' constructor to be invoked.
I have been looking, but not found an equivalent in c++. Is there one?
class B
{
static int i;
int j;
public:
B(int arg = 0) : j(arg) /* constructor */
{
}
};

int B::i = 42; /* initialize B::i with the value 42 */
class D : public B
{
static int m;
int k;
public:
D(int Bval, int kval) : B(Bval), k(kval) /* constructor */
{
}
};

int D::m = 10; /* initialize D::m with the value 10 */

int main()
{
B b_obj(99); /* create an object of type 'B', and
intialize it's member 'j' with the
value 99 */

D d_obj(25, 32); /* create an object of type 'D', initialize
its base portion (via its constructor 'B::B()')
with value 25, and initialize its member 'k' with
value 32 */
return 0;
}

If you tell us more specifically what you're trying to do,
perhaps we can offer more specific advice.

Which C++ book(s) are you reading?
-Mike
Dec 25 '06 #2
Mike Wahler <mk******@mkwahler.netwrote:

If you tell us more specifically what you're trying to do,
perhaps we can offer more specific advice.
I'm trying to write a base class for scriptable objects. The subclasses
of this class hold a set of properties that must be identified by name
(a string), that can be retrieved or set by a script. But never mind the
scripting, I just explain it so you can see why the properties must be
identified by names. When the member functions

int Scriptable::luaGetProperty( lua_State *lua, string &propertyName )
int Scriptable::luaSetProperty( lua_State *lua, string &propertyName )

are called on the scriptable objects, the respective subclasses must be
free to implement the getting and setting of these properties
themselves, so it's not possible to just let these properties be held by
some hashtable. It would be nice to let the subclass just forward the
requests to the following member functions:

int Scriptable::luaGetProperty( lua_State *lua, int propertyCode )
int Scriptable::luaSetProperty( lua_State *lua, int propertyCode )

which take an int code (i.e. an enum) instead of an action name, cause
then I can just use switch statements like this:

switch( propertyCode ) {
case HEIGHT_PROPERTY:
// perform code to get/set height
case WIDTH_PROPERTY:
// etc...
}

My problem is the following: I thought it would be a bad idea to
hardcode all property names and respective codes in the base class. So,
I thought I'd let the base class hold a registry of property names and
codes in a hashtable, as a static member shared by subclasses. Then, any
subclass that adds new properties, can call the function:

void Scriptable::registerPropertyCode( string &name, int code ) {
properties.put( name, code );
}

Where properties is the hashtable. In the main other language I've been
programming in (Objective-C), I would simply make the class initializer
call a static member function, declared something like this:

class Scriptable {

/.../

static void registerProperties();

/.../
};

So that any subclass can override this to add their own properties. I
thought the cleanest way to do this, would be to make the class
guarantee that the properties were registered before any instances of
the class were set into action. I might do it in the constructors,
though, but I thought it wouldn't be optimal. I'm sure there's a
workaround for this specific problem, but I'm trying to learn how to
solve this type of problems in the future
Which C++ book(s) are you reading?
"Core C++ A Software Engineering Approach" by Victor Shtern.

Per
Dec 25 '06 #3
Mike Wahler <mk******@mkwahler.netwrote:

If you tell us more specifically what you're trying to do,
perhaps we can offer more specific advice.
I'm trying to write a base class for scriptable objects. The subclasses
of this class hold a set of properties that must be identified by name
(a string), that can be retrieved or set by a script. But never mind the
scripting, I just explain it so you can see why the properties must be
identified by names. When the member functions

int Scriptable::luaGetProperty( lua_State *lua, string &propertyName )
int Scriptable::luaSetProperty( lua_State *lua, string &propertyName )

are called on the scriptable objects, the respective subclasses must be
free to implement the getting and setting of these properties
themselves, so it's not possible to just let these properties be held by
some hashtable. It would be nice to let the base class just forward the
requests to the following member functions:

int Scriptable::luaGetProperty( lua_State *lua, int propertyCode )
int Scriptable::luaSetProperty( lua_State *lua, int propertyCode )

which take an int code (i.e. an enum) instead of an action name, cause
then I can just use switch statements like this:

switch( propertyCode ) {
case HEIGHT_PROPERTY:
// perform code to get/set height
case WIDTH_PROPERTY:
// etc...
}

My problem is the following: I thought it would be a bad idea to
hardcode all property names and respective codes in the base class. So,
I thought I'd let the base class hold a registry of property names and
codes in a hashtable, as a static member shared by subclasses. Then, any
subclass that adds new properties, can call the function:

void Scriptable::registerPropertyCode( string &name, int code ) {
properties.put( name, code );
}

Where properties is the hashtable. In the main other language I've been
programming in (Objective-C), I would simply make the class initializer
call a static member function, declared something like this:

class Scriptable {

/.../

static void registerProperties();

/.../
};

So that any subclass can override this to add their own properties. I
thought the cleanest way to do this, would be to make the class
guarantee that the properties were registered before any instances of
the class were set into action. I might do it in the constructors,
though, but I thought it wouldn't be optimal. I'm sure there's a
workaround for this specific problem, but I'm trying to learn how to
solve this type of problems in the future
Which C++ book(s) are you reading?
"Core C++ A Software Engineering Approach" by Victor Shtern.

Per
Dec 25 '06 #4
Per Bull Holmen wrote:
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. Like, for instance
the Objective-C method:

+(void)initialize

Which has the following characteristics: It is guaranteed to be run
before the first instance of that particular class is created. It is a
static member function, which otherwise operates the same way as any
other such functions: It can be overridden by subclasses, and the
overridden can call the superclass' implementation if needed, etc...

I have been looking, but not found an equivalent in c++. Is there one?

Per
such a syntax does not exist in C++ but you can device the dummy
variable initialization technique:

class myclass{
private:
struct initializer{
initializer(){
//do write initialization code here
};//end initializer()
};//end struct initializer

friend struct initializer; /*grant initializer the permission to
axcess private members of mystruct*/

static initializer unused; //unused variable

}; //end class myclass

myclass::initializer myclass::unused(); //invoke initialization

Dec 25 '06 #5
terminator <fa***********@gmail.comwrote:
such a syntax does not exist in C++ but you can device the dummy
variable initialization technique:

class myclass{
private:
struct initializer{
initializer(){
//do write initialization code here
};//end initializer()
};//end struct initializer

friend struct initializer; /*grant initializer the permission to
axcess private members of mystruct*/

static initializer unused; //unused variable

}; //end class myclass

myclass::initializer myclass::unused(); //invoke initialization
Thanks.

I couldn't get the above code to work, I got a compile-time error. With
my present knowledge of c++, I couldn't figure out what was wrong, but I
tried to use the same idea slightly differently:

class myclass {

static bool initialized; //unused variable

static bool initialize() {
printf( "Init\n" );
return( true );
}

public:
myclass() {}

}; //end class myclass

bool myclass::initialized = myclass::initialize(); //invoke
initialization

This worked fine, but sometimes one might want to be guaranteed that all
superclasses' initializers get invoked before a subclass' initializer. I
couldn't do that without changing the constructors a bit, because the
order of initialization of static class members is undefined, and I
can't rely on some static bool initialized value being false if it
hasn't been - well - initialized. With the following code it worked:

class myclass {

static bool classInitialized;

static void initializeClass() {
printf( "Init base\n" );
classInitialized = true;
}

public:
myclass() {
if( ! classInitialized )
initializeClass();
}

}; //end class myclass

bool myclass::classInitialized = false;

class subclass : myclass {

static bool classInitialized;

static void initializeClass() {
printf( "Init sub\n" );
classInitialized = true;
}

public:
subclass() {
if( ! classInitialized )
initializeClass();
}

}; //end class myclass

bool subclass::classInitialized = false;

Since myclass' constructor gets implicitly invoked when a new instance
of subclass is created, this should guarantee that all superclasses get
initialized first. It seems that when an instance of subclass invokes
myclass' constructor, it uses the myclass::classInitialized variable
rather than subclass::classInitialized. Am I relying on undefined
behaviour here, or is this part of the c++ standard?

Per
Dec 25 '06 #6
Per Bull Holmen wrote:
Mike Wahler <mk******@mkwahler.netwrote:

If you tell us more specifically what you're trying to do,
perhaps we can offer more specific advice.

I'm trying to write a base class for scriptable objects. The subclasses
of this class hold a set of properties that must be identified by name
(a string), that can be retrieved or set by a script. But never mind the
scripting, I just explain it so you can see why the properties must be
identified by names. When the member functions

int Scriptable::luaGetProperty( lua_State *lua, string &propertyName )
int Scriptable::luaSetProperty( lua_State *lua, string &propertyName )

are called on the scriptable objects, the respective subclasses must be
free to implement the getting and setting of these properties
themselves, so it's not possible to just let these properties be held by
some hashtable. It would be nice to let the base class just forward the
requests to the following member functions:

int Scriptable::luaGetProperty( lua_State *lua, int propertyCode )
int Scriptable::luaSetProperty( lua_State *lua, int propertyCode )

which take an int code (i.e. an enum) instead of an action name, cause
then I can just use switch statements like this:

switch( propertyCode ) {
case HEIGHT_PROPERTY:
// perform code to get/set height
case WIDTH_PROPERTY:
// etc...
}

My problem is the following: I thought it would be a bad idea to
hardcode all property names and respective codes in the base class. So,
I thought I'd let the base class hold a registry of property names and
codes in a hashtable, as a static member shared by subclasses.
You want to respect the relationship between the base class and its
subclasses.
Not just use the base class as a universal repository of static
properties.

Its completely conceivable to have some static repository of properties
in your program, but don't put it in your base class. Let a static
collection of properties live outside of the class. That way, you can
create different Scriptable derivatives based on different sets of
static data.

See if the code below helps. Note that std::map is not neccessarily a
solution here. Its just a suggestion (std::maps load reletively slowly
but search/find is infinitely faster that an array with op[]). You
might also consider using a reference to a static collection in your
base class with a set of Scriptables referring to one static map
collection and another set of Scriptables referring to some other
static collection. The possibilities are endless.

Note the ctors that take an external std::map collection as a
parameter.

#include <iostream>
#include <ostream>
#include <map>

class Base
{
std::map< std::string, int properties;
public:
Base() : properties() { }
Base(std::map< std::string, int >& r_m) : properties(r_m) { }
Base(const Base& copy) { properties = copy.properties; }
virtual ~Base() { }
/* virtual member functions */
virtual void /* staggered to fit */
registerPropertiesCode(const std::string&, const int) = 0;
virtual int
getProperty(const std::string& r_s) const;
/* global friend op<< */
friend std::ostream&
operator<<(std::ostream&, const Base&);
};

void
Base::registerPropertiesCode(const std::string& r_s, const int n)
{
properties.insert( std::make_pair< std::string, int >(r_s, n) );
}

int
Base::getProperty(const std::string& r_s) const
{
typedef std::map< std::string, int >::const_iterator MIter;
MIter found = properties.find( r_s );
if(found != properties.end())
return (*found).second;
else
return -1;
}

std::ostream& operator<<(std::ostream& os, const Base& r_b)
{
typedef std::map< std::string, int >::const_iterator MIter;
for( MIter miter = r_b.properties.begin();
miter != r_b.properties.end();
++miter )
{
os << "property: " << (*miter).first;
os << "\t" << "value: " << (*miter).second;
os << "\n";
}
return os;
}

class Scriptable : public Base
{
public:
Scriptable() { }
Scriptable(std::map< std::string, int >& m) : Base(m) { }
Scriptable(const Scriptable& copy) : Base(copy)
{
}
/* required virtuals */
void
registerPropertiesCode(const std::string& r_s, const int n)
{
Base::registerPropertiesCode(r_s, n);
}
};

int main()
{
Scriptable instance;
instance.registerPropertiesCode("HEIGHT_PROPERTY", 60);
instance.registerPropertiesCode("WIDTH_PROPERTY", 100);
instance.registerPropertiesCode("XCOORD_PROPERTY", 10);
instance.registerPropertiesCode("YCOORD_PROPERTY", 0);

std::cout << "get WIDTH_PROPERTY: ";
std::cout << instance.getProperty("WIDTH_PROPERTY");
std::cout << std::endl;
std::cout << "get BOGUS_PROPERTY: ";
std::cout << instance.getProperty("BOGUS_PROPERTY");
std::cout << std::endl;

std::cout << instance << std::endl; // friend op<<

Scriptable copy(instance); // copy the properties
std::cout << copy << std::endl;

static std::map< std::string, int mycollection;
mycollection.insert(
std::make_pair< std::string, int >("FIRST_PROPERTY", 1) );
mycollection.insert(
std::make_pair< std::string, int >("SECOND_PROPERTY", 2) );
mycollection.insert(
std::make_pair< std::string, int >("THIRD_PROPERTY", 3) );

Scriptable another(mycollection);
std::cout << another << std::endl;
}

/*
get WIDTH_PROPERTY: 100
get BOGUS_PROPERTY: -1 // probably not appropriate
property: HEIGHT_PROPERTY value: 60
property: WIDTH_PROPERTY value: 100
property: XCOORD_PROPERTY value: 10
property: YCOORD_PROPERTY value: 0

property: HEIGHT_PROPERTY value: 60
property: WIDTH_PROPERTY value: 100
property: XCOORD_PROPERTY value: 10
property: YCOORD_PROPERTY value: 0

property: FIRST_PROPERTY value: 1
property: SECOND_PROPERTY value: 2
property: THIRD_PROPERTY value: 3
*/

Merry Xmas to all !!

Dec 25 '06 #7
Per Bull Holmen wrote:
terminator <fa***********@gmail.comwrote:
such a syntax does not exist in C++ but you can device the dummy
variable initialization technique:

class myclass{
private:
struct initializer{
initializer(){
//do write initialization code here
};//end initializer()
};//end struct initializer

friend struct initializer; /*grant initializer the permission to
axcess private members of mystruct*/

static initializer unused; //unused variable

}; //end class myclass

myclass::initializer myclass::unused(); //invoke initialization

Thanks.

I couldn't get the above code to work, I got a compile-time error.
I coud not either.this seems to be my mistake in syntax.but I removed
the braces in the last line and it compiled and worked.so change that
line to this:

/* outside class declaration of static member variable :constructing it
with default (none parameterd) constructor */
myclass::initializer myclass::unused;
/*myclass::initializer myclass::unused(); */ /*do not uncomment:
error on this line*/

In C++ you must declare static member variables outside the class and
select the constructor that initializes it.try this:

class myclass{
protected:
struct initializer{
initializer(){
printf("initialize default\n");
};//end initializer()

initializer(int data){
printf("initialize with: %d\n",data);
};//end initializer(int)

};//end struct initializer

friend struct initializer; /*grant initializer the permission to
axcess private members of mystruct*/

private:
static initializer svar1,svar2; //static variables

}; //end class myclass
myclass::initializer myclass::svar1 /* default constructor
*/
,myclass::svar2(13); /*parametered
constructor*/

struct subclass:
public myclass //inherit publicly
{// begin subclass

private:

typedef myclass::initializer InitializerBase; /*
declare a private nested type*/

protected:

class initializer:
private InitializerBase //inherit privately
{// begin class initializer

public:

initializer() {printf("subclass\n");};

initializer(char c) :
InitializerBase(c) /*choose parametered version
of base constructor*/
{// begin initializer (char)

printf("subclass with %c\n",c);

};// end initializer (char)

};// end class initializer

public:

static initializer sub1,sub2; //static stuff

};// end subclass

subclass::initializer subclass::sub1 /* default constructor */
,subclass::sub2('A');/*parametered
constructor*/

For the sake of implicit call to base class static constructor , have
every derived class`s initializer type to be a subclass of that of the
base class(in this case "struct initializer" must be not private ; so
have it protected).You can also put some of your static member
variables in initializer ,this increases encapsulation and "unused"
will not be unused any more .
With
my present knowledge of c++, I couldn't figure out what was wrong, but I
tried to use the same idea slightly differently:

class myclass {

static bool initialized; //unused variable

static bool initialize() {
printf( "Init\n" );
return( true );
}

public:
myclass() {}

}; //end class myclass

bool myclass::initialized = myclass::initialize(); //invoke
initialization

This worked fine, but sometimes one might want to be guaranteed that all
superclasses' initializers get invoked before a subclass' initializer. I
couldn't do that without changing the constructors a bit, because the
order of initialization of static class members is undefined, and I
can't rely on some static bool initialized value being false if it
hasn't been - well - initialized. With the following code it worked:

class myclass {

static bool classInitialized;

static void initializeClass() {
printf( "Init base\n" );
classInitialized = true;
}

public:
myclass() {
if( ! classInitialized )
initializeClass();
}

}; //end class myclass

bool myclass::classInitialized = false;

class subclass : myclass {

static bool classInitialized;

static void initializeClass() {
printf( "Init sub\n" );
classInitialized = true;
}

public:
subclass() {
if( ! classInitialized )
initializeClass();
}

}; //end class myclass

bool subclass::classInitialized = false;

Since myclass' constructor gets implicitly invoked when a new instance
of subclass is created, this should guarantee that all superclasses get
initialized first. It seems that when an instance of subclass invokes
myclass' constructor, it uses the myclass::classInitialized variable
rather than subclass::classInitialized. Am I relying on undefined
behaviour here, or is this part of the c++ standard?

Per
you are paying an unnecessary runtime overhead for checking
"classInitialized" for every instance of myclass.

Dec 26 '06 #8
terminator <fa***********@gmail.comwrote:
you are paying an unnecessary runtime overhead for checking
"classInitialized" for every instance of myclass.
I know. Not bad for a complete c++ newbie, though?? :)

Thanks for your help, I'll try your code later.

Per
Dec 26 '06 #9

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

Similar topics

2
by: tekenenSPAM | last post by:
I know that one cannot cast a non-static member function to a void *. (http://users.utu.fi/sisasa/oasis/cppfaq/pointers-to-members.html) However, I have a case where I need to call a certain...
1
by: Piotr Sawuk | last post by:
just a quick question out of curiosity: how to initialize const arrays? struct srat { long num; ulong den; srat(){} } struct collisions
8
by: Robert A Riedel | last post by:
I have an application that requires a DLL and an executable that uses the DLL, both of which were implemented in Visual C++ using unmanged code. Both the executable and the DLL are linked with...
4
by: mnowosad | last post by:
As far I know, static variables are tied to AppDomain scopes. So, every time an executing code within an AppDomain references a class for the the first time since the AppDomain was created/loaded,...
10
by: n.torrey.pines | last post by:
Are global variables (and const's) guaranteed to be initialized before static class members (and methods) ? const int x = 19907; int get_x() { return x; } // another compilation unit: ...
6
by: darkshaddow | last post by:
I am having trouble with a LNK2019 on a member function. Here is the error: main.obj : error LNK2019: unresolved external symbol "public: void __thiscall Stat::openFile(char *)"...
9
by: Jess | last post by:
Hello, I was told that if I declare a static class constant like this: class A{ static const int x = 10; }; then the above statement is a declaration rather than a definition. As I've...
3
by: Thomas Troeger | last post by:
Hello, I have a class that looks like this: class A(object): def __init__(self, a=0, b=1): self.a, self.b=a, b def __str__(self): return "%s(%d,%d)" % (type(a).__name__, self.a, self.b)
11
by: Andreas Wollschlaeger | last post by:
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...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

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.