C++ constructor syntax explaination - c++

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

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++ Multiple Inheritance Constructor

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.

How to create parameterized constructor of a class in another class as a data member?

In below example,
class Car
{
private:
int sides;
public:
Car()
{
cout<<"\ndefault called constructor";
}
Car(int nsides)
{
cout<<"\ncalled constructor";
sides=nsides;
}
};
class Auto
{
private:
Car ch;
public:
Auto(int a) : Car(a)
{
//Car test(5);
}
};
int main()
{
Auto at(5);
return 0;
}
After referring below links :-
create objects in object passing variables through constructor
http://www.cplusplus.com/forum/beginner/9746/
I tried to write the same and execute it.unfortunately I am getting following compiler error :-
check.cpp: In constructor ‘Auto::Auto(int)’:
check.cpp:44: error: type ‘Car’ is not a direct base of ‘Auto’
If solution mentioned in the given links are correct then what wrong in my code ? My next query is ...why only parametrized constructor() throws compiler if try to initialize it without using initialization list.
This will throw compiler error :-
class Auto
{
private:
Car ch(5);
public:
Auto(int a)
{
}
};
But this does not :-
class Auto
{
private:
Car ch;
public:
Auto(int a)
{
}
};
Please help me in understanding this behaviour.
Thanks in advance.
In your example you are specifying by your constructor Auto(int a) : Car(a) that Auto is derived from Car, and that's what the compiler complains about.
To initialize your Car object (inside of Auto), do this Auto(int a) : ch(a). You put the type instead of the member's name.
About your second question, in-class member initialization is a new feature brought by C++11. You may use it by adding the parameter -std=c++11 to your compiler (GCC or Clang, msvc doesn't support it). See this question. In your case you can use it as chris pointed out :
class Auto {
// ...
Car ch{5};
int someVal = 5;
// ...
};

Using a C++ child class instance as a default parameter?

So I have a couple classes defined thusly:
class StatLogger {
public:
StatLogger();
~StatLogger();
bool open(<parameters>);
private:
<minutiae>
};
And a child class that descends from it to implement a null object pattern (unopened it's its own null object)
class NullStatLogger : public StatLogger {
public:
NullStatLogger() : StatLogger() {}
};
Then I have a third class that I want to take an optional logger instance in its constructor:
class ThirdClass {
public:
ThirdClass(StatLogger& logger=NullStatLogger());
};
My problem is when I do it as above, I get:
error: default argument for parameter
of type ‘StatLogger&’ has type
‘NullStatLogger’
And if I put an explicit cast in the definition, I get:
error: no matching function for call
to
‘StatLogger::StatLogger(NullStatLogger)
Complaining about not having a constructor from a NullStatLogger even though it's a child class. What am I doing wrong here, is this allowed in C++?
I you want to use inheritance and polymorphism, ThirdClass needs to use either a pointer or a reference to StatLogger object, not with an actual object. Likewise, under the circumstances you almost certainly need to make StatLogger::~StatLogger() virtual.
For example, modified as follows, the code should compile cleanly:
class StatLogger {
public:
StatLogger();
virtual ~StatLogger();
// bool open(<parameters>);
private:
// <minutiae>
};
class NullStatLogger : public StatLogger {
public:
NullStatLogger() : StatLogger() {}
};
class ThirdClass {
StatLogger *log;
public:
ThirdClass(StatLogger *logger=new NullStatLogger()) : log(logger) {}
};
Edit: If you prefer a reference, the code looks something like this:
class StatLogger {
public:
StatLogger();
virtual ~StatLogger();
// bool open(<parameters>);
private:
// <minutiae>
};
class NullStatLogger : public StatLogger {
public:
NullStatLogger() : StatLogger() {}
};
class ThirdClass {
StatLogger &log;
public:
ThirdClass(StatLogger &logger=*new NullStatLogger()) : log(logger) {}
};
Based on the discussion in Jerry's answer, what about simplifying the problem by not using a default variable at all:
class ThirdClass
{
StatLogger log;
public:
ThirdClass() : log(NullLogger()) {}
ThirdClass(const StatLogger& logger) : log(logger) {}
};
There is no problem in using a derived instance as default argument for a base reference.
Now, you cannot bind a non-constant reference to a temporary (rvalue) which can be one reason for the compiler to complain about your code, but I would expect a better diagnose message (cannot bind temporary to reference or something alike).
This simple test compiles perfectly:
class base {};
class derived : public base {};
void f( base const & b = derived() ) {} // note: const &
int main() {
f();
}
If the function must modify the received argument consider refactoring to a pointer and provide a default null value (not a default dynamically allocated object).
void f( base * b = 0) {
if (b) b->log( "something" );
}
Only if you want to keep the non-const reference interface and at the same time provide a default instance, then you must provide an static instance, but I would recommend against this:
namespace detail {
derived d;
// or:
derived & null_logger() {
static derived log;
return log;
}
}
void f( base & b = detail::d ) {}
// or:
void g( base & b = detail::default_value() ) {}
Well for a default value I believe you have to provide a default value...
ThirdClass(StatLogger *logger = NULL)
for example
Uh, I know this is an oooold question, but I just had the exact same problem, and after reading all the proposed answers and comments, I came up with a slightly different solution.
I think it also might just be appropriate for the problem instance presented here, so here it goes:
Make the NullStartLogger a singleton type of object!
For me, it was quite elegant and sort. Very shortly, singleton is an object that you can not construct at will, since only and exactly one instance can exist at all time. (Alternatively, there might be 0 instances before the first usage, since you can postpone the initialization). You can of course only add the singleton functionality in to your derived class, while all the other instances (and derivations) of the parent class can be initialized and created normally. But, if NullStatLogger is, as it was in my case, just a dummy class, it does not store any data externally and does not have different behavior depending on the instance/init parameters, singleton class fits well.
Here's a short code snipped making your NullStatLogger a singleton, as well as a way to use it in the ThirdClass:
class NullStatLogger : public StatLogger {
private:
NullStatLogger() : StatLogger() {}
static NullStatLogger *_instance;
public:
static NullStatLogger &instance();
};
NullStatLogger::_instance = 0;
NullStatLogger &NullStatLogger:instance() {
if (_instance == 0)
_instance = new NullStatLogger(); // constructor private, this is
// the only place you can call it
return *_instance; // the same instance always returned
}
class ThirdClass {
public:
ThirdClass(StatLogger& logger=NullStatLogger::instance());
};
I know this surely won't help to whomever asked the question, but hopefully it helps someone else.