Call non-default constructor as member initialization - c++

I have a class "A", and a class "B" such that A contains an instance of B
class A
{
B b = B(parameters...);
Other thing = 3;
}
The problem with this code, is that B does not (and should not!) have a copy constructor, so the compiler is complaining
I would like to be able to call B's constructor like below, but it interprets it as a function declaration
class A
{
B b(parameters...);
Other thing = 3;
}
Is there a way to call the non-default constructor in the definition of the class?

Default member initializer (since C++11) only supports brace or equals initializer; you could use brace initializer here.
class A
{
B b{parameters...};
Other thing = 3;
};

If you need to make the copy constructor not visible you can make it private
Class B
{
public:
B(parameters...){};
private:
B(B b){};
}
As for your code i think your problem is that you need to initiate the member in the constructor of A like this:
class A
{
A()
: B(parameters...)
{
thing = 3;
}
B b;
Other thing;
}

Related

Calling the superclass' constuctor twice in the subclass' constructor

I have a user defined class, say A. I have another user defined class B which publicly extends A.
When I define the constructor of B, I have to call the constructor of A in the member initializer list of B's constructor, or else the compiler will call the default constructor.
class A {
int a;
public:
A(int x = 0) {
a = x;
}
};
class B : public A {
int b;
public:
B(int x = 0) : A(2*x) {
b = x;
}
};
Now, I understand the logic behind all this. However, what I want to know is what happens when I do this instead:
class A {
int a;
public:
A(int x = 0) {
a = x;
}
};
class B : public A {
int b;
public:
B(int x = 0) {
A(2*x);
b = x;
}
};
I mean, we all know that the compiler will call the default constructor of A before it enters the body of the B's constructor. Now, the first line of B's constructor body is to call another constructor of A (which takes arguments). So, what does this result in? Two different constructors of the superclass are getting called here whenever an object of the subclass is being created. Please explain what happens...whether two objects will be created or what.
That doesn't call the constructor for the A subobject of the B being initialised. Instead, it creates and destroys a temporary object of type A. The only way to call the constructor of the base subobject is through the initialiser list, as in the first example.
Now, the first line of B's constructor body is to call another constructor of A (which takes arguments). So, what does this result in?
It constructs a temporary A and the temporary object is discarded right away. That call has no relationship to initializing the A part of B.

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.

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++ how to write a constructor?

I'm not used to c++ and I'm having a problem writing a constructor.
See this example, is a short version of the code I'm working on:
class B {
public:
B(int x);
}
class A {
public:
B b;
A(){
// here I have to initialize b
}
}
That throws a compiler error since I need to initialize b in A's constructor because B does not have a default constructor.
I think I have do it in the initialization list, but the B(int x) argument is a value I have to calculate with some algorithm, so I don't know how this should be properly done, or if I'm missing something or doing it wrong.
In other language like java I would have a reference to B and initialize it inside the A's constructor after the other code I need to get the value for the initialization.
What would be the right way to initialize b in this case?
Thanks!
You can invoke functions in your constructor initializer list
class B {
public:
B(int x);
}; // note semicolon
class A {
public:
B b;
A()
:b(calculateValue()) {
// here I have to initialize b
}
static int calculateValue() {
/* ... */
}
}; // note semicolon
Note that in the initializer list, the class is considered completely defined, so you can see members declared later on too. Also better not use non-static functions in the constructor initializer list, since not all members have yet been initialized at that point. A static member function call is fine.
You use an initializer list, something like this:
A() : b(f(x)) {}
#include<iostream>
class B {
public:
B(){} // A default constructor is a must, if you have other variations of constructor
B(int x){}
}; // class body ends with a semicolon
class A {
private:
B b;
public:
A(){
// here I have to initialize b
}
void write(){
std::cout<<"Awesome";
}
};
int main(){
A a;
a.write();
}
In C++, if you have a constructor that takes an argument, a default constructor is a must, unlike other languages as Java. That's all you need to change. Thanks.

C++: newbie initializer list question

Newbie here. I am looking at company code.
It appears that there are NO member variables in class A yet in A's constructor it initializes an object B even though class A does not contain any member variable of type B (or any member variable at all!).
I guess I don't understand it enough to even ask a question...so what's going on here!? My intuition is that you need a variable before you even try to initialize it. How is it possible (or what good does it do) to initialize an object without having the object?
.h:
class A: public B
{
public:
A(bool r = true);
virtual ~A;
private:
}
.cpp:
A::A(bool r) : B(r ? B::someEnumeration : B::anotherEnumeration)
{
}
A::~A()
{
}
Please help.
Thanks,
jbu
Class A (publicly) inherits from class B:
class A: public B
The only way to initialize a base class with parameters is through the initializer list.
This is actually the only way to call the ctor of a base class in C++ as there is noch such thing as super().
class A : public B
{
};
class B
{
public:
int x;
};
A is a derived type from B. Or A inherits B.
So this is valid...
A a;
a.x = 3;
The rest of your code is just calling B's constructor when A is constructed.
class A: public B
{
public:
A(bool r = true); // defaults parameter 1 as "true" if no arguments provided ex A *pA = new A();
virtual ~A;
private:
}
.cpp
A::A(bool r) : B(r ? B::someEnumeration : B::anotherEnumeration)
{
// calls parent class, and initialize argument 1 with some enumeration based on whether r is true or false
}
A::~A()
{
}
Since construtor cannot be inherited so base class data members are to be initialized by passying argument in derived class constructor and with the help of initialization list.
You should also know that in case of polymorphic class initialization of vptr to respective virtual table is done only in constructor.