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.
Related
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.
I need to know something about the constructor. I didn't really know how to phrase the question, but basically I need to have all the action happening in the constructor of the final class, whilst a variable gets created in the constructor of one class and used in the constructor of another. Does this work, and is it safe? Example code below.
// Init class
class cInit {
private:
std::string *m_X;
public:
cInit() { m_X = new std::string; }
std::string *getX() { return m_X; }
};
// Does this work (?)
class cUse {
private:
std::string *m_X;
public:
cUse(cInit *x) : m_X( x->getX() ) { }
// Final Class - same question here? Does it work?
class Final : public cInit, public cUse {
public:
Final() : cInit(), cUse( this ) { }
}
Since base constructors are called in declaration order, cInit::cInit() will be called first. Its constructor would assign cInit::m_X member.
Then, cUse::cUse(cInit *) will be called and would assign a result of call to cInit::getX() to cUse::m_X. Given that cInit::getX() is not a virtual function, it is safe to call it like that.
In other words, there is nothing wrong with this code. Except that it is ugly (or should I say not well designed?), confusing, and would only cause troubles further down the road.
Hope it helps.
I would prefer the following design (as it's more RAII oriented):
// Init class
class cInit {
private:
std::string m_X;
public:
cInit() : m_X() {}
std::string & getX() { return m_X; }
};
class cUse {
private:
std::string& m_X;
public:
cUse(std::string &x) : m_X( x ) { }
// Final Class - same question here? Does it work?
In your sample you're using this, which isn't completely constructed at that point, though cInit already is. With vtables (virtual function definitions), usage of this will certainly fail.
Try the following instead:
class Final : public cInit, public cUse {
public:
Final() : cInit(), cUse( cInit::getX() ) { }
}
You can also use pointers as in your original sample, but I'd strongly discourage to use raw pointers all along. Better choose a std::unique_ptr (std::auto_ptr with pre c++11 standard) for cInit::m_X and a raw pointer for cUse::m_X.
I am going through Chapter 17 in the new Stroustrup book and I am confused by initializing a class with an initialization list.
Example:
in .hpp:
class A
{
public:
A() : _plantName(std::string s), _growTimeMinutes(int 1);
virtual ~A();
private:
std::string _plantName;
int _growTimeMinutes;
};
in .cpp:
A::A() : _plantName(std::string s), _growTimeMinutes(int i)
{
}
or is it in .cpp:
A::A(std::string s, int i) : _plantName(std::string s), _growTimeMinutes(int i)
{
}
and calling that:
A a {"Carrot", 10};
I learned c++ back in 1998 and have only programmed in it off and on over the years until recently. How long ago did this stuff change? I know I could still do that the older way but I really want to learn new!
First I think initialization lists are useful when when you are dealing with constant members or when passing objects as parameters since you avoid calling the default constructor then the actual assignement.
You should write the following code in your cpp file : no need to rewrite the parameters types in the initialization list.
A::A(std::string s, int i) : _plantName(s), _growTimeMinutes(i)
{
}
Your h file should be :
class A
{
public:
A(std::string, int);
private:
std::string _plantName;
int _growTimeMinutes;
};
And you should create a new A object like that
A new_object("string", 12);
It should be
A::A(std::string s, int i) : _plantName(s), _growTimeMinutes(i) {
}
for example
supposing the variables _plantName and _growTimeMinutes are declared within class A or one of its superclasses. s and i are the constructor parameters for class A, the initialization will then call the string-constructor for _plantName with argument s and the int-constructor for _growTimeMinutes with argument i, thus initializing both variables.
Initialization lists are especially needed if you want to initialize const references. The assignment within a constructor would not work.
Hope I could help
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
}
};
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