Doing necessary work before member initialization in constructor - c++

I've got a design question concerning classes and their constructors in C++. I'm coming from several years of Java experience. In Java, I would do things like this: I've got a class to manage an SQLite DB as a storage backend. In the constructor of this class, I would hand over the path to the applications data directory as a parameter. Then, I would look for the database file, instatiate a connection, and for example load the most current entry of a table for the purpose of caching.
My Problem now is how to do this in C++. My main problem here is that when execution reaches the first statement of the constructor, all class members were already initialized, either implicitly or explicitly.
My question now is: If I had some computations to do on the constructor parameters before using them to initialize the class members, how would I do that in C++?
I've already found that I can simply use assignment to the members in the constructors, but I've also read you should not do that, because it would mean that the members are first initialized with their default constructors, and then initialized again.
What is the canonical way when you have some computation to do (e.g. loading and parsing a configuration file) before class members can be initialized? I would prefer to simply give a path to the constructor, and then do the loading and parsing an member initialization with the loaded values inside the constructor.

Put the computation part in separate function:
class C {
std::string x;
int y;
C(int xarg, int yarg);
};
std::string computeX(int xarg, int yarg) {
...
return result;
}
C::C(int xarg, int yarg) : x(computeX(xarg, yarg)), y(yarg) {}
As the "initialisation" function you may use a global function, a function defined locally in the source file (e.g. in unnamed namespace), or even invoke a lambda defined in place. You can also use a static member function - also if it is private - or a member function of one of the arguments.

Related

A c++ class include a static member with the same type of itself. Why this pattern?

I inherited a project from a former colleague, and I found these code snippets (and some similar ones in SO questions: can a c++ class include itself as an member and static member object of a class in the same class)
// Service.h
class Service
{
// ...
public:
static Service sInstance;
void Somememberfunc();
//...
};
// Service.cpp
#include "Service.h"
Service Service::sInstance;
void Service::Somememberfunc()
{
//...
}
// Main.cpp
#include "Service.h"
void Fun()
{
Service &instance = Service::sInstance;
//...
instance.Somememberfunc();
//...
}
However, I did not find any explanation on when to use this pattern. And what are the advantages and disadvantages?
Notice that the member is a static, so it's part of the class, not of instantiated objects. This is important, because otherwise you would be trying to make a recursive member (since the member is part of the object, it also contains the same member and so on...), but this is not the case here.
The best pattern to describe this is: global variable. The static member is initialized before main() and can be accessed from any part of the program by including the header file. This is very convenient while implementing but becomes harder to handle the more complex the program gets and the longer you have to maintain it, so the general idea is to avoid this. Also, because there is no way to control the order of initialization, dependencies between different global variables can cause problems during startup.
Static member is roughly a global variable in the scope of the class.
Static members have also the advantage of visibility access (public/protected/private) to restreint its usage (file scope might be an alternative).
That member might be of type of the class.
Global are "easy" to (mis)use, as they don't require to think about architecture.
BUT (mutable) global are mostly discouraged as harder to reason about.
Acceptable usages IMO are for constants:
as for a matrix class, the null matrix, the diagonal one matrix.
for Temperature class, some specific value (absolute 0 (O Kelvin), temperature of water transformation(0 Celsius, 100 Celsius), ...)
in general NullObject, Default, ...
Singleton pattern. For example, you can use it to store your app configurations. And then you can easily access configurations anywhere(globally) within your app.
This is often used in the singleton design pattern
Visit https://en.wikipedia.org/wiki/Singleton_pattern

How To Initialize a Variable to Previously Allocated Memory?

I'm using C++, and am creating a ex_stage class (a SystemC module, if it makes any difference). In the header file for the class, I define:
public:
ReorderBuffer ROB;
Where ReorderBuffer is another class I have also defined, which has its own constructor. I have defined ROB as a global variable for the ex_stage class so that it can be accessed from multiple functions within ex_stage.
However, I cannot initialize ROB until runtime as it depends on user-supplied values for some of its functionality. So, even though I define ROB as a global variable, I cannot initialize it where it is defined.
Normally, I would do something like this:
ReorderBuffer ROB(<incoming variables>);
within the constructor of ex_stage to construct ROB at the same time. However, since I have already defined ROB, I'm not sure if I am able to do that without causing issues.
Will performing an operation like this actually affect ROB in its original scope, or will it create a new ROB with a scope local to the constructor of ex_stage?
P.S. - Sorry if this is hard to understand please let me know if you need more information.
When you want to initialize something global, you have to be careful about "Global initialization fiasco". If i were you, i would use an unnamed namespace to hide a global var pointer and have some global functions (just inside a named namespace) such as InitMyGlobalVar(), GetMyGlobalVar() to initialize and retrieve the pointer.
If you know how to initialize ROB when your ex_stage constructor runs, you might find a member initializer useful.
Member initializers allow class members to be initialized in a specific way, as opposed to just having their default constructors called:
class ex_stage {
public:
ex_stage() : ROB(<stuff>) {} // constructor that takes <stuff> will be called
ReorderBuffer ROB; // default constructor will _not_ be called
};

Why can I not initialize non-static member outside class declaration?

class ClassObject {
public:
ClassObject();
virtual ~ClassObject();
private:
int x;
};
int ClassObject::x=10;
Why does it fail to compile?
I think that if static members can be initialized this way, then it should also be possible for non-static ones.
Static members are special. They have a memory allocated to them as soon as the class is defined. And no matter how many objects of that class we create all those objects refer to the same piece of memory.
This is not the case with non static members. Unless you create an object of that particular class, the non static members are not allocated any memory and hence trying to instantiate them in the above way leads to compiler error.
I'm guessing you mean declaring the value used to initialise x for any new ClassObject, i.e. you mean that as equivalent to
ClassObject() : x(10) { }
The problem with your syntax is that the compiler needs to generate code to do that initialisation in every ClassObject constructor; i.e. it can only work if the int ClassObject::x = 10; initialisation is available in the compilation unit that defines all constructors, and any compilation units that generate one implicitly. And the only way to guarantee that is if the value is set inside the class definition, not outside it as you have. (However this is now possible in C++11 - see the link in tacp's comment.)
If we did want to make your syntax work, then we'd need to store the declared value as a hidden static somewhere in a way that any constructors would pick it up and know to use it as the initial value for x. However this static may or may not exist, and the only point we can know that for a constructor in a different compilation unit is at link time. Hence we either generate extra, redundant code to initialise x from this hidden static if it exists (or redundant data) or we mandate link-time-code-generation to solve this, which puts a large burden on the compiler developer. It is possible, yes, but it's simpler all around if this isn't allowed.

Strange "type class::method() : stuff " syntax C++

While reading some stuff on the pImpl idiom I found something like this:
MyClass::MyClass() : pimpl_( new MyClassImp() )
First: What does it mean?
Second: What is the syntax?
Sorry for being such a noob.
This defines the constructor for MyClass.
The syntax is that of a constructor definition with an initialization list (I assume there is a set of braces following this that define the body of the constructor).
The member pimpl_ of MyClass is being initialized as a pointer to a new object of type MyClassImp. It's almost the same as the following:
MyClass::MyClass()
{
pimpl_ = new MyClassImp();
}
However, it is preferable to use the initialization list for initializing class members wherever possible; see the C++ FAQ Lite entry linked above.
It's an initialization list.
It allow you to set the values of member and base class constructor before the constructor code is called.
You should use it to initialize the values of your class instance.
In addition to being a constructor with an initialiser list as others have already explained, it's also using the private implementation pattern.
C++ requires the class declaration to include all the public and private members of the class. This can result in you having to expose implementation details that you don't want to, and to making your implementation part of your API/ABI. It can also significantly increase compile times due to additional #includes in the public headers to support the private member variables.
Making a second class with the actual implementation and just exposing the functional API makes this much cleaner, but at the cost of an additional layer of indirection.
C generally handles this by having a pointer to an opaque object which the library creates and destroys for you.

Prevent creation of class whose member functions are all static

All the member variables and member functions in my class ClassA are static.
If a user is trying (by mistake) to create an object of this class, he receives a warning: "ClassA, local variable never referenced", because all the functions are static, so this object is never referenced. So, I want to prevent the user from trying to create an object of this class.
Would it be enough to create a private default (no variables) constructor? Or do I have to also create private copy constructor and private assignment operator (to prevent using the default constructors)? And if I do have to create them too, maybe it would be better just to create some dummy pure virtual function instead, and this will prevent the user from creating an object?
Thank you
Instead of using a class with all static methods, you may be better off making the methods free-standing functions in a separate namespace. The call syntax would be the same:
namespace::function() instead of classname::function()
and you don't need to deal with someone trying to instantiate your class.
Creating a private default constructor should be sufficient. Both of the other default constructs (copy constructor and assignment) rely on having an instance to work correctly. If there is no default constructor then there is no way to create an instance, hence no way to actually get to the copy construction part.
It would likely save you a few headaches though to define all 3 as private and not implemented.
Like others said, a namespace is what you should use. If you want to stay with your class, create a class that has a private constructor, and derive from it, to make your intention obvious:
class NonConstructible {
NonConstructible();
};
class SuperUtils: NonConstructible {
static void foo();
// ...
static std::vector<int> globalIDs;
// ...
};
Ok, now let's look into the namespace which are the one and only way to do this:
namespace SuperUtils {
void foo() {
// ....
}
std::vector<int> globalIDs;
};
You can call that using SuperUtils::foo(); in both cases, but the namespace has the advantage that in a scope you can use the namespace declaration and directive to bring certain or all members into the current scope, so that you can reference them without using SuperUtils:::
void superFunction() {
using namespace SuperUtils;
foo();
}
While generally that should be avoided, it can be helpful when the method is using exclusively much stuff from SuperUtils, which then can improve the readability of the code.
In order to use a copy constructor you have to have an object to copy, so if you've locked down the default constructor you should be safe.
The best way to prevent creation of non-heap objects is to make destructor private. Then there is no way compiler can destruct the object when it goes out of scope and it will complain.
This will not prevent anyone from doing new however.