Yet another C++ Object initialization interrogation - c++

I have this class that has many class members, and a lot of different constructors.
Until now, I used a constructor initialization list in each of the constructors that I have, tuning each member the way I wanted.
This is quite tedious, because everytime I add a new member to my class, I have to visit each constructor and update the initialization list to add a default value to this member.
So, I thought I would add a method to initialize the values I need. Problem! Since the method is executed after the initialization list, the particular values I put in this init list are overriden by my method.
Quick exemple:
class A
{
public:
A();
A( B b );
A( int i );
// A( .... ); plenty of them
private:
int member1, m2, m3,m4;
bool b1,b2, b3;
// ....
// every time I add a member I have to modify the initialization lists
// solution: agregate member initialization in a member function:
void init_members();
}
// init list constructors
A::A() : m1(false), m2(false), m3(false), m4(true) .... // looong list
{
}
A::A( B b) : m1(b.state()), m2(false), m3(false), ... // loong list
{
}
// problem, if I use init_members:
void A::init_members()
{
m1 = false;
m2 = false;
m3 = false;
// ...
}
A::A( int i ) : m1( true)
{
init_members(); // overrides m1 !!!
}
So, my question: can I mix list initializer and method initializers, so that list initializers have precedence over the method initializer?
In my example above, I want m1 to stay true for the last constructor.
Note: I know I could move the initialization list after the method call, but this means I'd assign twice the values to the members : once in init_members(), then overriding it in the constructor. Not optimal enough :-)
I was hoping for some little trick, if you have that in stock.

In C++11 one option could be constructor delegation, where one constructor simply calls one of the other constructors, so as to avoid duplicating code.
This is what it looks like:
class A {
public:
A(int,int,double);
A(int,int);
A(double);
A();
private:
...
};
A::A(int a,int b,double c) {
// the real work to initialize the class
}
// A(int,int) delegates to A(int,int,double), passing along a
// default value for the double
A::A(int a,int b) : A(a,b,0.0) {}
A::A(double c) : A(1,2,c) {} // A(double) delegates to A(int,int,double)
A::A() : A(1.0) {} // A() delegates to A(double)
Make sure you don't create any loops. Also typically you'll want a single constructor to do most of the real work while the others just marshal the values they want to pass to that constructor. We'll call this the 'designated constructor'. The designated constructor should be the one that takes the most parameters and doesn't use any default values. Eventually all the constructors should call the designated constructor, directly or indirectly.
Note the pattern: constructors that use some default values pass those defaults along to constructors that use fewer defaults, until you arrive at the function with no defaults at all. This is the opposite of what you're trying to do with your init_members() method. You have a function that sets all the defaults, and then you try to override some of them. If you can't use C++11 features, you would be better off emulating the designated constructor pattern: init_members() will be your designated initializer and it will not have any defaults. You can use an initializer method for each constructor which takes the arguments it's given, and throws in a few default values to call another init_members overload.
However one issue with the designated initializer/constructor is that the defaults are scattered all over the place. Another option in C++11 besides delegation is 'in-class initialization', which allows all the default values to be gathered together.
class A {
public:
A(int,int,double);
A(int,int);
A(double);
A();
private:
int a = 1,b = 2; // in-class initialization gathers all the defaults together
double c = 1.0;
};
Given the above, all constructors will automatically initialize the member values to those defaults unless you explicitly initialize it to something else in that constructor.
A::A(int a,int b,double c) : a(a), b(b), c(c) {}
A::A(int a,int b) : a(a), b(b) {} // member c is automatically initialized to 1.0
A::A(double c) : c(c) {} // members a and be are automatically initialized to 1 and 2
A::A() {}; // all members are initialized with their in-class values.
Here's an example of using init_members():
class A {
public:
A(int a,int b,double c) { init_members(a,b,c); }
A(int a,int b) { init_members(a,b); }
A(double c) {init_members(c);}
A() { init_members(); }
private:
void init_members(int,int,double) { ... }
void init_members(int a,int b) { init_members(a,b,1.0); }
void init_members(double c) { init_members(1,2,c); }
void init_members() { init_members(1.0); }
...
};
This method value initializes members before init_members() can be called, so members are initialized twice. I'm not sure there's a way to fix that in C++03.

For cases like this, I do not use the Base/Member Initializer List (the members have "garbage" or "default-constructor" values at that point in the constructor), and I use the init_() function (called from the constructor-body). Then, the constructors call the init_() function, and there is a single maintenance point.
Similarly, my clear() function would also call the init_() function, for a single maintenance point of "default" values.
For your case, it would be:
A::A(void)
//...no Base/Member-Initializer list...
{
init_members();
}
A::clear(void)
{
init_members();
}
...and the override:
A::A(int override_m1)
{
init_members();
m1 = override_m1;
}

Hm, I don't want to know what names your colleagues give you if they spot a class like this... Imagine what happens if they have to repair or extend a monster of this kind. I newly assigned a task to switch some of the many As we have in our code base (and which became unmaintainable) to something like this:
class AKeyValueStorage {
// would be some kind of shared storage if meant to be
// copyable and don't forget moving if your're on c++11!
std::map<std::string, boost::any> mMembers;
public:
template<class Key, class T>
T const & Get(Key const & pKey) const
{
auto tTmp = mMembers.find(ToString(pKey));
if (tTmp != mMembers.end()) {
return boost::any_cast<T const &>(*tTmp);
}
// throw if none, or return default
}
template<class Key, class T>
void Set(Key const & pKey, T const & pValue) const
{
mMembers[ToString(pKey)] = pValue; // replace if found, insert if none
}
};

Related

Calling default constructor instead of overloaded with default parameter

I need a class like that:
class MyClass
{
MyClass()
{
}
public:
MyClass(signed = 0)
{
}
}
I'm wondering if it's possible to call these constructors selectively. Actually what I need is to have two versions of constructors. One to create object with default value like second constructor in my example and the other one to create a default/raw/uninitialized object without any parameters which is used internally in the same class.
I can do following to get over this problem:
class MyClass
{
MyClass(float)
{
}
public:
MyClass(signed = 0)
{
}
}
And to call the first constructor inside my class but it's weird to have unused parameter.
You have a few options. Your "work-around" isn't crazy, and in fact it's a pattern that is encouraged in some circumstances. But consider the named-constructor idiom instead: If you need to create an uninitialized object in a member function of the same class, then create a named private c'tor that achieves this for you:
class MyClass {
public:
MyClass(float f = 0.) : value_{f} {}
private:
float value_;
void g();
MyClass invalid()
{
return MyClass{std::numeric_limits<float>::max()}; }
};
That way, inside of MyClass::g(), you can do:
void MyClass::g()
{
auto newObj = invalid(); // call named c'tor
newObj.value_ = 3.14159;
std::swap(newObj, *this) // swap current object with 'newObj'
// or whatever.
}

object construction : default parameter vs delegation

Consider the following code where I'm trying to introduce a default constructor as well as a parameterized one for class A. This way was introduced in recent c++ improvements.
class A {
private:
unsigned int count;
public:
A(int new_c) : count(new_c) {}
A() : A(10) {}
};
vs the old way of setting a default parameter on parameterized constructor and ignoring the default constructor completely.
class A {
private:
unsigned int count;
public:
A(int new_c = 5) : count(new_c) {}
};
Is there any advantage using 1st method over the 2nd one apart from following modern conventions?
Functionally there is no difference. Know that there is even another option available with non-static member initialization (since C++11):
class A {
private:
unsigned int count = 10;
public:
A() = default;
A(int new_c) : count(new_c) {}
};
There is no advantage in case like in your example (I'd even choose the 2nd option as more clear in such example)
Delegating constructors where added to ease work when default values were not enough.
For example
struct Point3d
{
Point3d(int x, int y, int z);
Point3d(Point2d p) : Point3d(p.x, p.y, 0) {}
}
Advantage will be more visible in case of larger class where can be a few constructors . In new way you will be able to write one constructor and then set it to others. This is less error prone.
class A {
private:
unsigned int count;
int other;
float otherfloat;
public:
A( unsigned int count, int other, float otherfloat ) : count( count), other( other ), otherfloat( otherfloat ) {}
A(int new_c) : A(new_c, 0, 0.0 ) {}
A() : A(10) {}
};
While technically there is no difference, the idea behind the creation of forwarding constructors was a different one.
Imagine the following class:
class sample {
complexType member;
bool createdWithInt;
public:
sample() : member(5), createdWithInt(false) {
/* code ... */
}
sample(int param) : sample() {
createdWithInt = true;
/* other code */
}
};
So this class is hard to implement with default parameters:
Its behaviour does not depend on the value of the parameter, it rather depends on the presence.
One might to try to implement it with a helper function void creator() that executes the code ... bit from the constructor without arguments. However this would mean duplicating the initialization list (or discarding the RAII principle if one initializes from within creator()).
Note: createdWithInt could be initialized from the initialization list, if another constructor was added, that takes a bool and both current constructors forward to that one. For the sake of the example this has been omitted.

C++ private member variables same name as ctor params

I know that many peoplpe use a prefix or suffix for private member variable names. For those who don't, but just use the name - how do you initialize them if you want to have constructor params of the same name?
By simply writing them. The rules of the language prevent problems.
struct Foo
{
Foo(int x) : x(x) {};
int x;
};
Outside the (), only the data member is in scope; inside, the function argument hides the member just as it would in a normal function body:
int x = 2;
void foo(int x)
{
// any access to `x` means the argument
}
This is one of many reasons that I do not use the m_ prefix style (or equivalent) when naming data members.
The simplest way is to use a mem-initializer list. For example
class A
{
private:
int data;
public:
A( int data ) : data( data ) {}
};
If you want to use the data member within the constructor's body then there are two approaches to distinguish the data member and the parameter
class A
{
private:
int data;
public:
A( int data ) : data( data )
{
A::data *= data;
this->data *= data;
}
};
You just initialize them in the initialization list:
struct foo
{
foo(int bar) : bar(bar) {}
private:
int bar;
};
Note that the initialization list is the only way to explicitly initialize a member in a constructor. Once you're in the body of the constructor, the member has already been initialized.
As an aside, C++ allows you to initialize a member at the point of declaration, in which case it is initialized to that value unless otherwise initialized in the constructor:
struct foo
{
foo(int bar) : bar(bar) {}
foo() {} // bar initialized to 42
private:
int bar = 42;
};
If you use an initializer list, you can simply use the same name and the compiler will understand what you mean.
Example:
Book::Book(std::string title, int year)
: title(title), year(year)
{}
The method formal name is not of high value, considering how limited it's scope is. And yet there should still be motivation to be able to instantly distinguish these items 'origins' at a glance.
It has become my practice to both
a) prefix my data attribute names with 'm_',
AND
b) prefix the method / function parameter names with 'a_' or 'an_', always striving for grammatical correctness.
LMBM::Node::Node(uint8_t a_max) : m_max (a_max) ...
void* LMBM::Node::threadEntry(void* an_objPtr) ...
void DV1::processDirent(const std::string& a_dirPath) ...
void DV1::handleDT_REG (DV::Dirent* an_ent,
const std::string& a_path) ...
FInfo (const std::string& aPfn, const int64_t& aFileSz) :
m_pfn (aPfn),
m_fileSz (aFileSz) ...
Goal - easier to read
Motivation - code is written once, read many times
I understand the special case for the ctor initializer list. But I am also confident that the use of prefixes (of your choice) do help prevent several kinds of mistakes that occur during development and maintenance.

C++ constructor syntax explaination

I was going through a tutorial for building an AST with the help of Clang/LLVM.
I see this syntax there:
struct PPContext {
// Takes ownership of client.
PPContext(clang::DiagnosticClient* client = 0,
const std::string& triple = LLVM_HOSTTRIPLE)
: diagClient(client == 0?new clang::TextDiagnosticPrinter:client),
diags(diagClient),
target(clang::TargetInfo::CreateTargetInfo(triple)),
headers(fm),
pp(diags, opts, *target, sm, headers)
{
// Configure warnings to be similar to what command-line `clang` outputs
// (see tut03).
// XXX: move warning initialization to libDriver
using namespace clang;
diags.setDiagnosticMapping(diag::kind,diag::MAP_IGNORE);
//diag::warn_pp_undef_identifier was the initial value instead of diag::kind. But I changed since it gave error.
}
~PPContext()
{
delete diagClient;
delete target;
}
clang::DiagnosticClient* diagClient;
clang::Diagnostic diags;
clang::LangOptions opts;
clang::TargetInfo* target;
clang::SourceManager sm;
clang::FileManager fm;
clang::HeaderSearch headers;
clang::Preprocessor pp;
};
And:
//What is the constructor doing here ? The construct looks very different and difficult to comprehend !!!
// Could someone break it up for me ?
PPContext(clang::DiagnosticClient* client = 0,
const std::string& triple = LLVM_HOSTTRIPLE)
: diagClient(client == 0?new clang::TextDiagnosticPrinter:client),
diags(diagClient),
target(clang::TargetInfo::CreateTargetInfo(triple)),
headers(fm),
pp(diags, opts, *target, sm, headers)
{
// Configure warnings to be similar to what command-line `clang` outputs
// (see tut03).
// XXX: move warning initialization to libDriver
using namespace clang;
diags.setDiagnosticMapping(diag::kind,diag::MAP_IGNORE);
//diag::warn_pp_undef_identifier was the initial value instead of diag::kind. But I changed since it gave error.
}
Please let me know if there is any other material which would be of good help and learning experience. Thanks
These are constructor initializers. They initialized class members with the value given to them. For instance:
class TestClass
{
private:
int someField;
public:
TestClass() : someField(5) { }
};
Will initialize the member someField to have a value of 5 during the call to the TestClass() constructor. You can separate multiple initializers with a , to initialize multiple members. You can also pass parameters from the constructor to these initializers such as:
class TestClass
{
private:
int someField;
public:
TestClass(int _someField) : someField(_someField) { }
};
When this constructor is called, the value passed to _someField will be used to initialize someField.
Also consider inheritance. Using the second TestClass as our base we get the following derived type:
class TestClassDerived : public TestClass
{
public:
TestClassDerived(int _someField) : TestClass(_someField) { }
};
That's how you can construct a base class from a derived type and pass parameters to a non-default constructor. Without this you wouldn't be able to construct the base with the appropriate parameters using a non-default constructor.
It's called a constructor initialization list, which is used for inheritance and initializating member variables.
Click this link for a good explanation of this topic.
One scenario this is required is dealing with inheritance. Consider the following:
class Base
{
public:
Base(int n)
{
}
};
class Derived : Base
{
public:
// Error! How do we construct Base? We never pass n
// to the constructor of Base.
Derived(int n)
{
}
};
How can we change the above to compile? With a constructor initialization list:
class Base
{
public:
Base(int n)
{
}
};
class Derived : Base
{
public:
// Now your compiler is happy.
Derived(int n) : Base(n)
{
}
};
This constructur is in the format
PPContext(arg1, arg2)
: initConstructor1,
...,
initConstructor5
where you can exchange initConstructor to the initialization constructors of
the PPContext members

Copy constructor not called, but compiler complains that there's no

Given the following code:
#include <boost/noncopyable.hpp>
enum Error { ERR_OK=0 };
struct Filter : private boost::noncopyable
{
Filter() {}
virtual ~Filter() {}
virtual int filter(int* data) const = 0;
};
struct SpecialFilter : public Filter, private boost::noncopyable
{
inline SpecialFilter(unsigned int min, unsigned int max) : min(min), max(max) {}
virtual ~SpecialFilter() {}
virtual int filter(int* data) const
{
// ...
return ERR_OK;
}
unsigned int min;
unsigned int max;
};
struct AClass
{
AClass() {}
AClass(const AClass& other) {}
~AClass() {}
int specialFilter(int channel, int minThreshold, int maxThreshold)
{
// ...
return filter(channel, SpecialFilter(123, 321));
}
int filter(int channel, const Filter& filter)
{
// ...
return ERR_OK;
}
};
My compiler (GCC 4.2) complains:
- warning: direct base ‘boost::noncopyable_::noncopyable’ inaccessible in ‘SpecialFilter’ due to ambiguity
- noncopyable.hpp: In copy constructor ‘Filter::Filter(const Filter&)’:
- noncopyable.hpp:27: error: ‘boost::noncopyable_::noncopyable::noncopyable(const boost::noncopyable_::noncopyable&)’ is private
- synthezised method first required here: [return filter(channel, SpecialFilter(123, 321));]
But I don't call the copy constructor!
You never call copy constructor. The copy constructor is always called for you implicitly by the compiler. So you need to learn to recognize situations when it might be called.
When you attach a const reference to a temporary object
...
return filter(channel, SpecialFilter(123, 321));
...
the compiler has the right to perform a copy of the temporary object and require an accessible copy constructor (even if it won't be actually called). This is what is causing the problem in your case.
In other words, when you make some type non-copyable, you also give up the possibility to attach const references to temporary objects of that type.
Firstly, remove the private derivation from SpecialFilter - it is not necessary, as Filter is already not copyable. Problems like this are why I think solutions like boost::non_copyable are a bad idea - there are simpler ways of saying you don't want copies.
Secondly, though I'm not sure this is your problem, C++ says that a public copy constructor must be available to the compiler under several circimstances, even if the compiler does not actually use it.
Remember when you pass object and return object by value --> copy constructor is invoked.