开发者

Why is there no "initialization" keyword in C++, as there is in Delphi?

Before switching to C++, we found the initialization language element in Delphi extremely useful. It allowed you to have code in each unit which would be called when the program was started, so you could initialize various elements of that unit.

This does in our opinion make things easier and help开发者_高级运维s to keep the code clean.

  • So why is there no initialization and finalization in C++?

  • What are our options for replacements of this language feature in C++?


The equivalent C++ feature is constructors and destructors for file-scope/global objects. For instance:

#include <iostream>
using std::cout;

struct X {
   X() { cout << "X::X()\n"; }
   ~X() { cout << "X::~X()\n"; }
};

static X x;

int main() { cout << "main()\n"; return 0; }

will output

X::X()
main()
X::~X()

when run.

It is generally considered unwise to use this feature, because you have no control whatsoever over the order in which these constructors and destructors are executed, which means things may get initialized before their dependencies, producing hard-to-debug crashes.


In C++ constructor/destructor pairs are generally used for this sort of thing. Be careful when using static objects, however. Two things you should read if you want to do this:

  1. What's the "static initialization order fiasco"?

  2. How do I prevent the "static initialization order fiasco"?


Question 1: why isn't there a keyword?

No-one apart from Stroustrup or the committee members can really answer why C++ is how it is, but we can speculate, probably that it wasn't considered important enough for a keyword. The C++ standard does talk about order of initialization, such as for objects but the order is not strictly defined and left to the implementation. Here's one quote (3.6.2/3):

It is implementation-defined whether or not the dynamic initialization (8.5, 9.4, 12.1, 12.6.1) of an object of namespace scope is done before the first statement of main. If the initialization is deferred to some point in time after the first statement of main, it shall occur before the first use of any function or object defined in the same translation unit as the object to be initialized

Question 2: how to achieve the equivalent of the Delphi initialization and finalization keywords?

There are two options. The first has been mentioned by other posters and I don't want to copy their answers: declare an object in a certain scope (translation unit or namespace) and its constructor and destructor will be called 'sometime'; do work there.

Note that the order of this is implementation-defined, so you're already in uncertain territory.

The second option is also compiler dependent. You're using Delphi, so am I right in thinking you're using C++ Builder to compile your C++ code? If so, C++ Builder and some other compilers support the #pragma startup and #pragma exit pragmas. These pragmas call a method at a certain time when your program is starting up or shutting down.

Personally I find this a neater solution, for two reasons:

  • It specifies exactly when something will occur and I can see it written down in code

  • It allows you to call a function, instead of using a constructor or destructor. This is aesthetically cleaner and lets you write, say, initialization() and finalization() methods which perform your work. This probably gets you as close to the Delphi syntax as you can get.

You can use these pragmas to call a procedure (which takes no parameters and returns void) and also optionally specify when it should occur, using a number between 64 and 255. You need to do this only if the order of initialization or finalization matters. A higher number is called first and priorities of 0-63 are reserved. For example:

void initialization(void) { foo = 3; bar = 5; /* Do useful work here */ }
#pragma startup initialization 200

void finalization(void) { foo = 0; bar = 0; /* Do useful work here */ }
#pragma exit finalization 200

The call chain is managed by the linker and you can run into issues if you use more compiler-specific constructs, such as weak packaging, but in general this is the technique I would recommend.


Class have constructors and destructors that you can use to intialize and clean up.

I think the closest you get to "code units" in C++ is classes.


Write a class with a constructor (initialization code) and a destructor (finalization code). Declare a singleton instance of this class; the constructor will be called at startup, and the destructor before the program shuts down.


Typically, it's viewed as a code smell in C++ to have global state that needs construction or destruction, and even if you did have this, you would just declare a class that does this in it's constructor and define a file-global instance of it.


In C++ you call the constructor (equivalent to your destructor) the same name of you class and the destructor the same name of you class, prefixed with tilde (~):

Class Point {
    public:
    Point() {  }
    ~Point() { }
}


The closest feature C++ has to what you are use to is static variables (specifically, static member variables).

// A.h
class A
{
public:

private:
    static int someValue;
};

// A.cpp
int A::someValue = 2;

The static variable is initialized at program startup. There is no automatic "finalization" procedure for static members (you would have to write your own cleanup function and call it).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜