How does constructor delegation interact with non-static data member initialization? - c++

Say I have some code like this:
class Foo
{
public:
Foo(int v) : value(v) {}
Foo() : Foo(42) {}
private:
int value = 666;
};
Does the default ctor set value to 42 or 666? I guess I would hope for 42 since that is an explicit call but I could imagine the other way too.
How about with inheritance?
class Base
{
public:
Base() { }
virtual ~Base() { }
virtual int f() = 0;
};
class Bar : public Base
{
public:
Bar(int _i) : Base(), i(_i) { }
Bar() : Bar(-1) { }
virtual ~Bar() { }
virtual int f() { }
private:
int i = 777;
};
Again, I would hope for i == -1.
Thanks.

The in class body member initializer is just a default. If the member initializer list of a constructor initializes the member too, it takes precedence always.
This is specified by 12.6.2p9 in the C++11 spec.

Related

In C++, do derived classes need its own constructors defined if it only requires constructors from the base class? [duplicate]

While working with templates I ran into a need to make a base class constructors accessible from inherited classes for object creation to decrease copy/paste operations.
I was thinking to do this through using keyword in same manner with functions case, but that not work.
class A
{
public:
A(int val) {}
};
class B : public A
{
};
class C : public A
{
public:
C(const string &val) {}
};
class D : public A
{
public:
D(const string &val) {}
using A::A; // g++ error: A::A names constructor
};
void main()
{
B b(10); // Ok. (A::A constructor is not overlapped)
C c(10); // error: no matching function to call to 'C::C(int)'
}
So my question: Is there any way to import a base class constructors after new ones in inherited class been declared?
Or there is only one alternative to declare new constructors and call a base ones from initializer list?
Yes, Since C++11:
struct B2 {
B2(int = 13, int = 42);
};
struct D2 : B2 {
using B2::B2;
// The set of inherited constructors is
// 1. B2(const B2&)
// 2. B2(B2&&)
// 3. B2(int = 13, int = 42)
// 4. B2(int = 13)
// 5. B2()
// D2 has the following constructors:
// 1. D2()
// 2. D2(const D2&)
// 3. D2(D2&&)
// 4. D2(int, int) <- inherited
// 5. D2(int) <- inherited
};
For additional information see http://en.cppreference.com/w/cpp/language/using_declaration
Prefer initialization:
class C : public A
{
public:
C(const string &val) : A(anInt) {}
};
In C++11, you can use inheriting constructors (which has the syntax seen in your example D).
Update: Inheriting Constructors have been available in GCC since version 4.8.
If you don't find initialization appealing (e.g. due to the number of possibilities in your actual case), then you might favor this approach for some TMP constructs:
class A
{
public:
A() {}
virtual ~A() {}
void init(int) { std::cout << "A\n"; }
};
class B : public A
{
public:
B() : A() {}
void init(int) { std::cout << "B\n"; }
};
class C : public A
{
public:
C() : A() {}
void init(int) { std::cout << "C\n"; }
};
class D : public A
{
public:
D() : A() {}
using A::init;
void init(const std::string& s) { std::cout << "D -> " << s << "\n"; }
};
int main()
{
B b; b.init(10);
C c; c.init(10);
D d; d.init(10); d.init("a");
return 0;
}
No, that's not how it is done. Normal way to initialize the base class is in the initialization list :
class A
{
public:
A(int val) {}
};
class B : public A
{
public:
B( int v) : A( v )
{
}
};
void main()
{
B b(10);
}
You'll need to declare constructors in each of the derived classes, and then call the base class constructor from the initializer list:
class D : public A
{
public:
D(const string &val) : A(0) {}
D( int val ) : A( val ) {}
};
D variable1( "Hello" );
D variable2( 10 );
C++11 allows you to use the using A::A syntax you use in your decleration of D, but C++11 features aren't supported by all compilers just now, so best to stick with the older C++ methods until this feature is implemented in all the compilers your code will be used with.
class A
{
public:
A(int val) {}
A(string name) {}
};
class B : public A
{
using A::A;
};
Addition to other answers, in case there are several constuctors with the base class, and you just want to inherit some of them, you can delete the unwanted.
class B : public A
{
using A::A;
B(string) = delete;
};
Here is a good discussion about superclass constructor calling rules. You always want the base class constructor to be called before the derived class constructor in order to form an object properly. Which is why this form is used
B( int v) : A( v )
{
}

Unable to access inherited variable

In the following example, why am I unable to assign to the inherited variable a in my derived class bar?
#include <iostream>
class foo
{
protected:
int a;
};
class bar : public foo
{
public:
bar(int _a) : a{_a} {}
int GetA() const { return a; }
};
int main() {
bar b{5};
std::cout << b.GetA() << std::endl;
return 0;
}
I receive the following compiler error:
prog.cpp: In constructor 'bar::bar(int)':
prog.cpp:12:16: error: class 'bar' does not have any field named 'a'
bar(int _a) : a{_a} {}
^
Doesn't my bar class now have a variable bar::a? Or does it only have access to foo:a?
The compiler is correct. The class bar doesn't have any data members. It's parent does.
A traditional method is to use the Parent class' constructor:
class foo
{
protected:
foo(int value) : a(value)
{ ; }
int a;
};
class bar : public foo
{
public:
bar(int value)
: foo(value)
{ ; }
};
Another method is to access the foo variable in the constructor:
bar(int value)
{
foo::a = value; // parent scope added for emphasis.
}
You can access foo::a from the derived class bar, but not initialise it in the constructor's initialiser list. That can only initialise the base class directly. Thus, you should instead
class foo
{
protected:
foo(int _a) : a(_a) {} // initialise member
int a;
};
class bar : public foo
{
int b;
public:
bar(int _a) : foo{_a}, b(0) {} // initialise base, then member
int GetA() const { return a; } // fine: access protected member of base
};

How to use a copy constructor with a base class?

I'm confused about base classes and copy constructors.
Say I have a class
class A {
public:
A(int m) : m(m) { return; }
virtual ~A() { return; }
int m;
}
And a class that inherits this
class B : public A {
public:
B(int n, int m) : A(m), n(n) { return; }
vitual ~B() { return; }
int n;
}
When I copy class B, how do I ensure that the m value in class A is copied as well?
The default copy constructor will copy all of the member variables, no matter whether they reside in the base class or a derived class.
If you create your own copy constructor for class B you will need to copy the class A members yourself, or better yet use the copy constructor for class A in the initializer list.
class B : public A {
public:
// ...
B(const B & b) : A(b), n(b.n) {}
// ...
};
The base copy constructor will be called before the derived copy constructor automatically. It's the same as for a regular constructor. (More accurately, the base constructor is called by derived initialization list before derived constructor continues). In your case, the default copy constructors are sufficient.
Be careful, however, that you do not copy a B into an A (search object splicing).
This code is your code just copy constructors are added with a class:
#include <iostream>
using namespace std;
struct Int
{
Int ()
{
}
Int(const Int&)
{
cout<< "Int copied" "\n";
}
};
class A
{
Int m;
public:
A(Int m) : m(m)
{
}
virtual ~A()
{
}
};
class B : public A
{
Int n;
public:
B(Int n, Int m) : A(m), n(n)
{
}
virtual ~B()
{
}
};
void f(B)
{
}
int main()
{
Int m,n;
B b(m,n);
cout<< "\n" "start:" "\n";
f(b);
cout<< "end";
}
Ubuntu Qt Creator Output says both are copied.
One can think there's a hidden member with type B in A and this hidden member can be initialized or copied as a usual member as in the above program with:
B(Int n, Int m) : A(m), n(n)
You should not return from a constructor/destructor, not even void.

Overriding Private Members of Parent Class

Given the following classes:
class foo
{
private:
int c;
public:
foo( int a = 42 ) { c = a; }
~foo();
};
class bar: public foo
{
public:
bar();
~bar();
};
How can I make bar override c with a different number? Can I do something like this?
bar::bar()
{
c = 12;
}
I get this error when trying to compile:
test.cpp: In constructor ‘bar::bar()’:
test.cpp:8:7: error: ‘int foo::c’ is private
Call your base class' constructor in the constructor initialization list:
bar::bar()
: foo(12)
{ }
Incidentally, you should always prefer using a constructor initialization list over assignment inside the constructor body, so your foo constructor would be better written as:
foo( int a = 42 ) : c(a) { }
Call the base class constructor:
bar::bar() : foo(12) { }
Edit: whoops
You should use getter and setter methods for your private variables.
So your calls foo should look like this:
class foo
{
private:
int c;
public:
foo( int a = 42 ) { c = a; }
virtual ~foo();
void setC (int tempC){
c=tempC;
}
int getC() const{
return c;
}
};
In the constructor of B you can call them the setter method:
bar::bar()
{
setC(12);
}
You should then always use your setter and getter methods to access your variable, instead of accessing it direct.
You should also declare your destructor of your base class virtual.
What about
bar::bar() : foo(12) {}

Initializing an abstract class?

Here is my issue. I want to have something like this:
class A {
protected:
int someInt;
virtual void someFunc() = 0;
};
class B : public A {
protected:
virtual void someFunc() { // uses someInt}
public:
B() {//tell the A inside of B to set someInt to whatever it wants}
};
so basically, someInt can be changed, it's not constant, but I want all the classes that implement A to use a value provided by A for someInt.
Thanks
You can use initializer lists in the constructor to call parent constructors:
class A {
protected:
int someInt;
virtual void someFunc() = 0;
A(int x) : someInt(x) {} // Base-class constructor (initialises someInt)
};
class B : public A {
protected:
virtual void someFunc() {}
public:
B() : A(10) {} // Initialises base class via constructor
};
Is this what you want?
class A
{
protected:
int someInt;
public:
A(int _val) : someInt(_val)
{
}; // eo ctor
}; // eo class A
class B : public A
{
public:
B() : A(5) // initialise someInt with 5
{
}; // eo ctor
}; // eo class B
Note, that as "someInt" is protected, you can just set it in B's constructor anyway.
B()
{
A::someInt = 5;
}; // eo ctor
I am not sure what you want, but if you initialize someInt in the constructor of A, subclasses will see that value.
class A {
public:
A() : someInt(5) {}
protected:
int someInt;
virtual void someFunc() = 0;
};
class B : public A {
protected:
virtual void someFunc() { // uses someInt}
public:
B() {// at this point someInt will already have been initialized to 5}
};
When the subclass is constructed, the baseclass constructors are executed first.
class A {
protected:
int someInt;
virtual void someFunc() = 0;
A(){//set someInt here}
};
class B : public A {
protected:
virtual void someFunc() { // uses someInt}
public:
B():A() {}
};
A protected constructor will achieve this. As above. The solutions using a public constructor are fine too, but as the constructor cannot be called directly on thr interface I think protected is better.