I'm currently maintaining a legacy C++ application which has put all the global application details in a static class, some of the variables stored are:
application name
registry path
version number
company name etc..
What is the recommended method for storing and accessing system application details?
If it never changes then why not. However, if not I'd externalise it into data that's loaded at run time. This way it can change without rebuild.
And since you include version number, I'd suspect the latter is way to go.
From my C++ days I recall builds taking not inconsequential times.
I'd rather use a namespace if no instances of the class will be created.
no hurt, and I think to use a singleton is even better.
Related
I had a program written using Qt's shared library version (5.2.0) and it displayed fonts okay (presumably filling it's Database from /usr/share/fonts). (Not sure whether the Designer text is from the same Database as the programmed font handling.) But then I recompiled it under the open source static version (5.2.0), and the fonts went ugly.
I disrupted the path to the installed Qt (since the whole idea of the static version is to be independent of development directories) and sure enough it complained of not being able to access any fonts. So I concluded Qt changed their static version to no longer input /usr/share/fonts. A little research on the internet told me they instead look under ...somedir/lib/fonts.
With a little more research I found I could use env var QT_QPA_FONTDIR to set the directory of search (though I suspect it might have been reduced to a one-level search, not recursive). Not wanting to have to write a script to wrap the program and set the environment variable before calling it, I proceeded to use a putenv() in the program. I chose a place that I thought would set the variable before Qt read the environment, and since global contructors are called before main() and certainly before QApplication is instantiated, I put it in a constructor.
But, guess what, they seem to read the environment before my constructor set the QT_QPA_FONTDIR=/usr/share/fonts.
So please help!!!! How do I make MY constructor get executed first?
Some compilers offer pragmas that attempt to help you do such things, but the simple truth is that C++ offers no guarantees of the order of global construction between modules. There isn't even a guarantee that one object dependent on another in another module will be initialized second. Globals are a minefield in this respect.
If you need a portable solution, there really isn't one.
If you can guarantee your compiler will always be the same flavor, then you can use hacks like pragmas, attributes, or link order to work around the problem. For instance, gcc offers a variable attribute called init_priority, though I'm not sure you can make your priority higher than the default.
Really, it would be better to solve the problem another way.
Thank you Aiken Drum. The link order worked. I created the smallest .cpp that made a constructor to be instantiated globally calling the putenv() to set up my environment. I put it first in the .pro file, and checked that the makefile it created had it first in the link line. And, hey presto!! the Qt program now gets the font Database from the right place. Thank you so much. It's the link order that sets the constructor order (at least with GCC).
The DYNAMIC FACTORY pattern describes how to create a factory that
allows the creation of unanticipated products derived from the same
abstraction by storing the information about their concrete type in
external metadata
from : http://www.wirfs-brock.com/PDFs/TheDynamicFactoryPattern.pdf
The PDF says:
Configurability
. We can change the behavior of an application by just changing its configuration
information. This can be done without the need to change any source code (just change the descriptive information about the type in the metadata repository) or to restart the application (if caching is not used – if caching is used the cache will need to be flushed).
It is not possible to introduce new types to a running C++ program without modifying source code. At the very least, you'd need to write a shared library containing a factory to generate instances of the new type: but doing so is expressly rules out by the PDF:
Extensibility / Evolvability
. New product types should be easily
added without requiring neither a
new factory class nor modifying
any existing one.
This is not practical in C++.
Still, the functionality can be achieved by using metadata to guide some code writing function, then invoking the compiler (whether as a subprocess or a library) to create a shared library. This is pretty much what the languages mentioned in the PDF are doing when they use reflection and metadata to ask the virtual machine to create new class instances: it's just more normal in those language environments to need bits of the compiler/interpreter hanging around in memory, so it doesn't seem such a big step.
Yes...
Look at the Factories classes in the Qtilities Qt library.
#TonyD regarding
We can change the behavior of an application by just changing its configuration information.
It is 100% possible if you interpret the sentence in another way. What I read and understand is you change a configuration file (xml in the doc) that gets loaded to change the behaviour of the application. So perhaps your application has 2 loggers, one to file and one to a GUI. So the config file can be edited to choose one or both to be used. Thus no change of the application but the behaviour is changed. The requirement is that anything that you can configure in the file is available in the code, so to say log using network will not work since it is not implemented.
New product types should be easily added without requiring neither a new factory class nor modifying any existing one.
Yes that sounds a bit impossible. I will accept the ability to add ones without having to change the original application. Thus one should be able to add using plugins or another method and leave the application/factory/existing classes in tact and unchanged.
All of the above is supported by the example provided. Although Qtilities is a Qt library, the factories are not Qt specific.
About the last year I did Java(Android)-programming, and did C# the Year before that. About a month now I'm learning C++, and since I got over friends, inheritance and stuff, I got a few questions, since I haven't been working with it up until now:
Is there a way for a class to define friends later on, because they need to exchange information or something. e.g. is there a way to define a 'random' friend later on? what do you need for that? The function's name or the address of the class?
Or is there generally a way to change the code from the program itself, so that it won't be necessary to recompile? e.g. creating new functions, classes or so?
I'd be very happy about any answer about that.
What you want to do is not possible with C++. If you need that sort of dynamically changing the program, you are better advised using a more dynamic higher-level language like Lisp.
friends can only be added to a class by modifying its source code. This is a feature, not a bug.
There are two ways to extend functionality like that.
Use dynamically loaded modules with the extended functionality. These modules supply a specific interface, and can be compiled separately from the main program.
Add support for scripting - allow users to add write scripts, and run them from inside your program.
The first solution is easier, depending on how much control you want to give those scripts.
DirectX 9 / C++
Do you declare d3ddevice global to your entire app/game or do you pass into classes that require the d3ddevice?
What is the usual way?
I understand it (and this may be wrong) that if you declare it globally, all classes and functions will be burdened by header memory that declares that global variable within the class after compiling?
I can be more specific about my question my application but, I'm just looking for the typical way.
I know how to start the d3ddevice etc, it's just a question about what is best?
I would recommend you wrap everything within a class and never put anything in global because global variables can be accessed from anywhere and that can make it very hard to keep track of the variable and who is and isn't using it.
Little bit late to the party here, but I also just recently stumbled into this same design question. It's a little surprising to me that there isn't more talk about it on the internet. I even tried perusing random github libraries to see if I could glean how others did it. Didn't find much. I also have an example of when you can't declare the d3d device as a global/static object. For my game/engine, I have a dll which serves as my engine framework. This dll is consumed by both an editor, and a game client (what people will use to play my game). This allows both things (and other applications in the future if desired) to access all of the world objects, math code, collections, etc.
With that system, I can't think of a way to make the Device object static, and still use it in both the editor and the client. If this were just a game client, or just an editor, then sure, it would be possible. Instead, I've pretty much decided to bite the bullet and pass Device to whatever needs it. One example, is a class that generates vertices at runtime. I need a pointer to Device for rebuilding the class.
I really just wanted to post this here, because I've been thinking about it for most of the day, and it really seems like this is the best way to handle it. Yeah, it sucks to have to pass the Device to nearly everything. But there's not really anything you can do about it.
I'm trying to get this thing with using different ClassLoaders to work with no success and I'm getting kind of desperate. What I'm trying to do is to launch 2 different instances of a 3rd party program that was created with several static attributes and therefore can't just be instantiated twice in my code. I've been advised to use different ClassLoaders to load the .jar file, though I don't really know how to do this. Could I maybe get some pointers on where I could start?
I also need to pass an object of my own program to this program instance and I also have no idea of how I could do this...
Thanks in advance for the help,
Andre
PS: This whole discussion started in the java forums, so there's a more detailed description of what I need to do and why I need to do this. The advice I'm referring to in this post was from malcommmc:
Another approach might be to run the
whole system in one JVM, but create a
new classloader for each instance of
the 3rd party code and make sure that
the classes containing the offending
statics are only loadable by these new
class loaders. Under these conditions
the JVM can support multiple copies of
the same class, providing the FQN is
unique within a class loader.
In this case run each instance as a
separate Thread, and set the thread's
context class loader to point to the
relevant class loader.
Presumably the object you are
proposing to pass is specified with
some interface or abstract class known
to the 3rd party app. You need that
interface to be known to the system
class loader, i.e. on the class path,
but the principal classes of the 3rd
party app must not be on the
classpath, but be accessed as a jar
referenced by a URLClassLoader.
This was already solved in the Java forums - link provided in the question