class member initialization in c++11 done properly - c++

I am trying to update some older code for Objects (A) with big initialization lists by initializing the member variable for Object (B) in the header.
class A
{
public:
A(); //a lot of members initialized in constructor
A(const A &cpy); //has a defined cctor too
B* member1 = new B("needs a string"); //works fine
B member2 = B("needs a string"); //error: ‘B::B(const B&)’ is private
B member3("needs a string"); //error: expected identifier before string
B member4{(const char*)"needs a string"}; //What I was looking for
}
But I need non pointer members too but can't find a way to initialize them. For various reasons I can not use the copy constructor of B.

Here it follows an example of your code once fixed:
#include <string>
class B {
public:
B(std::string) { }
};
class A {
public:
A() { }
A(const A &cpy) { }
B* member1{new B{"needs a string"}};
B member2{"needs a string"};
};
int main () {
A a;
}
This works, that's the best one can do with such a question.

Related

initialization of class member in anonymous union

I have observed that the following code segfaults at the line ar.p():
#include <iostream>
class A
{
public:
virtual void p() { std::cout<<"A!\n"; }
};
class B : public A
{
public:
void p() { std::cout<<"B!\n"; }
};
struct Param
{
enum {AA, BB} tag;
union {
A a;
B b;
};
Param(const A &p)
: tag(AA) {a = p;}
A &get() {
switch(tag) {
case AA: return a;
case BB: return b;
}
}
};
int main() {
A a;
a.p();
Param u(a);
A &ar = u.get();
ar.p();
}
However, when I change the Param constructor to:
Param(const A &p)
: tag(AA), a(p) {}
it does not segfault anymore.
I think it has something to do with the way the vtable ptr for union member a is initialized, but I'd like to understand this bug better.
On coliru: http://coliru.stacked-crooked.com/a/85182239c9f033c1
The union doesn't have an implicit constructor, you have to add your own constructor to the union which initializes one of the members of the union. I think this is because the compiler can't know whether you want to initialize a or b. You may also need an assignment operator and destructor. See also this question: Why does union has deleted default constructor if one of its member doesn't have one whatsoever?
The constructor should use placement new or it can use a member initializer to construct one of the union members, as you do in your alternative constructor.
If you want to assign something to b afterwards, you have to destruct a using a.~A(), and then initialize b with placement new.
If you have members in the union with a non-trivial destructor then the union must have a destructor which calls the destructor on the member which is used at that point.
In your original code the assignment operator and the p() method are called without running a constructor first, leading to the crash.

Do we "inherit" constructors in C++ ? What's is exact definition of "inheriting"

I wonder why people say:
"Inheriting class doesn't inherit the constructor".
If you could CAN use the parent class' constructor, and the parameterless constructor are called automatically no matter what.
Example:
#include <iostream>
using namespace std;
class A {
private :
int x;
public :
A () {
cout << "I anyway use parameter-less constructors, they are called always" << endl;
}
A (const int& x) {
this->x = x;
cout << "I can use the parent constructor" << endl;
}
};
class B : public A {
private :
int y;
public :
B() {
}
B (const int& x, const int& y) : A (x) {
this->y = y;
}
};
int main() {
B* b = new B(1,2);
B* b1 = new B();
return 0;
}
http://ideone.com/e.js/6jzkiP
So is it correct to 'say', constructors are inherited in c++ ? What is exact definition of "inherit" in programming languages ?
Thanks in advance.
I wonder why people say: "Inheriting class doesn't inherit the constructor".
Perhaps it is best to illustrate this with an example:
struct Foo
{
Foo(int, int) {}
};
struct Bar : Foo
{
};
What it means is that there is no Bar::Bar(int, int) constructor that you can call, despite the existence of a constructor with the same parameter list in the base class. So you cannot do this:
Bar b(42, 42);
In C++11, you can actually inherit constructors, but you must be explicit about it:
struct Bar : Foo
{
using Foo::Foo;
};
Now, you can say Bar b(42, 42);
What they mean is that constructor signatures are not inherited.
In your example, B does not have a constructor taking a single const int& even though its base class does. In this sense it has not "inherited" the constructor (but can still make use of it).
I think what they mean is:
struct A {
A(int, int) { }
};
struct B : public A {
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // error
}
To compare with “non-special” member functions:
struct A {
void f() { }
};
struct B : public A {
};
int main()
{
A a;
B b;
a.f(); // ok
b.f(); // ok too
}
But of course, from within B you can call accessible A constructors (as automatically generated ones do). Ditto for the destructor.
Note that in C++11 you can use the “inheriting constructors” feature:
struct A {
A(int, int) { }
};
struct B : public A {
using A::A;
};
int main()
{
A a(1, 2); // ok
B b(1, 2); // ok now
}
A derived class can/must see base class constructors in order to invoke them, for consistency. However, their signature is not exposed in the derived class, hence, one cannot construct the class without an explicitly defined constructor, which forwards the required arguments to the base class constructor.
In C++11, one can inherit constructors: What is constructor inheritance?
Another approach to circumvent 'proxy constructors' in C++ < 11: How to define different types for the same class in C++
In your example, the default ("parameterless" as you say) constructor of B does invoke the default constructor of A, but this does not mean that B "inherited" that constructor, only that it "has access to" it. That is, A's default constructor is accessible from within B, yet it is not accessible from outside (no one can use A's default constructor from outside to construct an instance of B).
Another way to look at it is to ask, what is something frustrating about constructors and inheritance in C++? A common answer from some people (including myself) would be that there is no automatic facility which allows "pass-through" construction of base classes taking arguments from derived class constructors without explicitly declaring and defining the latter.

error with const member and default constructor

I have two versions of a C++ code. One give the problem and other does not:
/*
* This compiles fine
*/
class base {
private:
const char c;
};
int main() {
base b(); // compiles fine
}
/*
* This gives compilation error
*/
class base {
private:
const char c;
};
int main() {
base b; // error: structure 'b' with uninitialized const members
}
Note the difference is 'base b()' and 'base b'.
I thought that both will call default constructor and since the class has a const field, the program will fail to compile.
Please help to explain this.
That is because the first version does not create an object of type base, but rather declares a function called b which takes no argument and returns an object of type base:
base b; // Declares an object b of type base
base b(); // Declares a FUNCTION called b that takes no argument an returns a base
In fact, you could try the following to verify that this is indeed the case:
int main() {
base b(); // DECLARES function b()
b(); // INVOKES function b()
}
base b() // DEFINITION of function b()
{
base c;
// ...
return c;
}
Now function main() won't give you problems anymore, but the base c; inside the b() function will. Exactly like the base b; in your original example. Why?
Well, because in general data members whose type is const-qualified should be initialized as soon as you construct the object (just like data members of a reference type). A way to guarantee this in general is to initialize those data members in the constructor's initialization list.
This, for instance, will compile:
class base {
public:
base() : c('x') { }
private:
const char c;
};
int main() {
base b;
}
const char c; Must be defined when declared.
const char c = 'a'; for example

Declaration vs. Instantiation

Comming from Java, I have difficulty with the code below.
In my understanding b is just declared on line 3 but not instantiated.
What would be the text book way of creating an instance of B in class A?
class A {
private:
B b;
public:
A() {
//instantiate b here?
}
};
Edit: What if B does not have a default constructor?
You could explicitly initialize b in A's constructor's initialization list, for example
class A {
B b; // private
public:
A : b() {} // the compiler provides the equivalent of this if you don't
};
However, b would get instantiated automatically anyway. The above makes sense if you need to build a B with a non-default constructor, or if B cannot be default initialized:
class A {
B b; // private
public:
A : b(someParam) {}
};
It may be impossible to correctly initialize in the constructor's initialization list, in which case an assignment can be done in the body of the constructor:
class A {
B b; // private
public:
A {
b = somethingComplicated...; // assigns new value to default constructed B.
}
};
You have created an instance of b in line 3. This line is enough so that B's constructor is called. If you have code like this
class A {
private:
B *b;
public:
A() {
//instantiate b here?
}
};
then it would make sense to instantiate b in A's constructor like
A()
{
b = new B();
}
The correct phase your looking for is "C++ initialization list". This initialization list is called/initialized before the constructor is called
In case of Default constructor, compiler equvalient constructor will be A() : B() {}
A very good reference
http://www.cprogramming.com/tutorial/initialization-lists-c++.html
At line 3, it is simply a declaration of B. However somewhere in your code where you have:
A a;
or
A a();
This calls the constructor of A. The internal b private member is full or garbage, as in not initialized. You are correct in that you can and probably should initialize member variable during construction where possible. There are two ways to do this:
A ()
{
b = B ();
}
Like you said:
or
A () : b (B())
{
}
The second version (initialization list) is slightly more efficient since it creates the new B object directly inside b. Whereas the first version creates a temporary and then moves that into b. This is the case when you initialize members from passed in parameters anyway (for non built in types). I'm making an assumption its the same in this case, but someone will be able to clarify.

C++ OOP basics (assigning an object as a member)

I'm a PHP developer trying to write some C++.
I'm having trouble with assigning an object as an another object's property. In PHP, I'd write this:
class A {
public $b;
}
class B {
}
$a = new A;
$a->b = new B;
How do I do that in C++? I got this so far:
class A {
B b;
public:
void setB(&B);
};
class B {
};
void A::setB(B &b)
{
this->b = b;
};
A * a = new A();
B * b = new B();
a->setB(b);
What am I doing wrong?
Just do this:
class B
{
};
class A
{
B b;
};
int main()
{
A anA; // creates an A. With an internal member of type B called b.
// If you want a pointer (ie using new.
// Then put it in a smart pointer.
std::auto_ptr<A> aPtr = new A();
}
You don't actually need to create the B separately. The B b is part of the class and is created (using the default constructor) automatically when the A object is created. Creating the two objects seprately and then combining them is a bad idea.
If you want to pass some parameters to the B object as it is constructed. That is easy to do by creating a constructor for A that calls B's constructor:
class B
{
public:
B(std::string const& data) // The B type takes a string as it is constructed.
:myData(data) // Store the input data in a member variable.
{}
private:
std::string myData;
};
class A
{
public:
A(std::string const& bData) // parameter passed to A constructor
:b(bData); // Forward this parameter to `b` constructor (see above)
{}
private:
B b;
};
int main()
{
A a("Hi there"); // "Hi there" now stored in a.b.myData
}
Instead of &B, you mean B&.
class A {
B b;
public:
void setB(B&); //<--
};
A pointer cannot be implicitly dereferenced. So a->setB(b) won't compile. You need to write a->setB(*b).
You don't need new to construct an object. For example, this works:
A a;
B b;
a.setB(b);
Don't use idioms from other languages directly in C++. For example, setters and getters are seldom needed. In fact, your A class could just be a simple struct.
A couple changes will make it compile:
1. class B needs to be declared before A so that it can be used in class A
2. The declaration setB(&B) needs a minor change to setB(B&)
class B {
};
class A {
B b;
public:
void setB(B&);
};
void A::setB(B &b)
{
this->b = b;
};
int main ()
{
A * a = new A();
B * b = new B();
a->setB(*b);
}
To make it more efficient consider the adding the following constructor that accepts B as an argument and the initializes the member variable 'b'. This will use a copy constructor on the 'b' member variable instead of using the default constructor and then the assignment operator.
A(B& b_) : b(b_)
{
}
There are a lot of things wrong with this code:
As KennyTM notes, the ampersand is in the wrong place.
You are passing a B* to a function that takes a B&, they aren't the same in C++
The design shown in your php fragment appears to misdesigned. While what you are doing is something you might want to do at times, you'll usually want to use a constructor instead, C++ and PHP alike.
You are putting code directly in the file, this isn't allowed in C++, put it in the main function instead
memory management: you are using new without delete (or a smart pointer class)
You are using class B in class A while class A doesn't know about class B (it is defined later) - you should put class B on top (or perhaps use forward declaration)
A few ways to make your code work properly are shown below.
include <memory>
using std::auto_ptr;
class B
{
}
class A
{
public:
A();
SetB(B& b);
private:
B b1; // a B made in the constructor
B b2; // a COPY of the original B you make
}
A::A()
: b1(/*whatever you want to pass to B's constructor*/)
{
}
A::SetB(B& b)
{
b2 = b;
}
int main(int agrc, char** argv)
{
A firstA();
B firstB();
firstA.SetB(firstB);
A* secondA = new A();
B* secondB = new B();
secondA->SetB(*secondB);
auto_ptr<A> thirdA(new A());
auto_ptr<B> thirdB(new B());
thirdA->SetB(*thirdB);
// whatever other code
delete secondA;
delete secondB;
}
Note that id you call SetB only once (and there is no problem with cyclic depndencies between the different objects you are creating), but you do want the flexibility of constructing the B outside the class, you can instead make a parameter of the constructor.
Also note that you are making a copy of the B you create in main - if you want to use the came copy in the class (as you would in PHP), you should use a member reference (in which case you will need to set what it refers to in the constructor, you can't do so in the SetB function.
Then, note that there are serious problems with the secondA, secondB approach and as such it is not recommended (above nothing will go wrong, however, it is easy to get code that leaks memory this way (and hard to find out where the leak is) and on top of that when you want to use exceptions, you will need exception safe code, which is not achievable using plain old pointers.
Lastly, note that you mix and match here. There is no problem at all with using firstA and thirdB together, for example.