Manually calling constructor of base class outside initialization list - c++

I have a Derived class whose constructor has to populate the fields of a struct that is passed as an argument to the constructor of the Base class. I want to be able to name the fields of the struct that I am populating, to keep my code future-proof (i.e.: resistant to addition and/or reordering of the members of MyStruct).
Note that struct MyStruct has default values, so it cannot be initialised with named fields directly in the initialization list (e.g.: Base({.a = a, .b = b}) does not work). Also, in my case, Base's copy constructor is deleted. Also, I am using C++ 11.
The solution I came up with uses the placement new operator to manually call the constructor of the Base class on the memory pointed to by this. To achieve this I also had to add a protected default constructor to my Base class. Are there any possible downsides to this approach and/or could anyone suggest a better method?
#include <iostream>
struct MyStruct
{
int a = 0;
int b = 1;
};
class Base
{
public:
Base(MyStruct str){
std::cout << "a: " << str.a << ", b: " << str.b << "\n";
}
Base(Base&&) = delete; // no copy constructor
protected:
Base(){ // dummy, does exactly nothing.
// it only exists to be called by
// the derived class's constructor
}
private:
int amember;
};
class Derived : public Base
{
public:
Derived(int a, int b)
{
MyStruct str;
str.a = a;
str.b = b;
new (this) Base(str);
}
private:
int anothermember;
};
int main()
{
MyStruct str;
str.a = 10;
str.b = 20;
Base b(str);
Derived d(10, 20);
return 0;
}
edit: added mention that Base cannot be copied, made explicit that Base::Base() does exactly nothing.

Use a helper function instead like
class Derived : public Base
{
public:
Derived(int a, int b) : Base(make_mystruct(a, b)), anothermember(some_value) {}
private:
int anothermember;
static MyStruct make_mystruct(int a, int b) { return MyStruct(a, b); }
};

I would just like to add that this could be a good opportunity to use IILE, Immediately Invoked Lambda Expression, if you for whatever reason don't want a named helper function:
class Derived : public Base
{
public:
Derived(int a, int b) : Base{[](){
MyStruct str;
str.a = a;
str.b = b;
return str; }()}
{}
};
The benefit is that you will not need to construct the class and it's members only once, since you do everything in the initialization list. If you in the future add non-trivial members to Base, you will be will not have to pay for double initialization.

Related

How to access inherited class attribute from a third class?

The goal of the code structure below is to be able to store pointers to objects of any class inherited from 'A'.
When I run this code, I get 0 written out, but what I'm trying to access is the 'B' object's 'num' value, which is 1. How can I do that?
As far as I know, when you create an inherited class's object, you create an object of the parent class too automatically. So can I somehow access the parent class object from it's child and set it's class member to match?
See minimal reproducible example below.
Update: Virtual functions solved the problem.
#include <iostream>
class A
{
public:
int num;
A()
{
num = 0;
}
};
class B : public A
{
public:
int num;
B()
{
num = 1;
}
};
class C
{
public:
A* ptr_array[2];
C()
{
ptr_array[0] = new B();
}
void print()
{
std::cout << ptr_array[0]->num << std::endl;
}
};
int main()
{
C* object_c = new C();
object_c->print();
return 0;
}
The problem is that you define a member num in A, and another member num in B. So an object of type B has two members called num, and you're leaving it to the compiler to choose which one to use -- which it does, according to logical rules which may be unfamiliar to you.
If you remove the line in num; from the definition of B, the code will work as you intend.
Your array is a red herring. You are only using one pointer. Might just as well have it as a member for the sake of the example.
I suppose you might need something like this (note, untested code).
#include <memory>
#include <iostream>
class A {
public:
A() : m_num(0) {} // use this instead of assignment in the c'tor body
virtual int getNum() { return m_num; } // this is **the** way to use inheritance
virtual ~A() = default; // required
private:
int m_num;
};
class B : public A {
public:
B() : m_otherNum(1) {}
virtual int getNum() { return m_otherNum; } // does something different from A
private:
int m_otherNum; // you could also call it m_num, but for clarity I use a different name
};
class C {
public:
C() : m_a (std::make_unique<B>()) {} // note, use this instead of new B
void print() {
std::cout << m_a->getNum() << std::endl;
}
private:
std::unique_ptr<A> m_a; // note, use this instead of A* m_a;
};
I have no way of knowing if this is really what you need (or you think you need). This is how inheritance is supposed to be used in object-oriented programming. You can use it in various other ways and produce correct (as far as the language definition is concerned) programs. But if this is the case, then (public) inheritance is likely not the best tool for the job.

Trying to use a virtual function in my initialization list

I am trying to create a base and a derived class with a const member that has to be initialized:
class baseClan
{
public:
baseClan(const string firstName)
:
fullName(createFullName(firstName))
{}
private:
const string lastName = "Smith";
const string fullName;
virtual const string createFullName(string firstName) { return firstName + " " + lastName ; }
}
How do I implement the derived class so that it can use a differently implemented createFullName? I am looking at this link
https://isocpp.org/wiki/faq/strange-inheritance#calling-virtuals-from-ctor-idiom
but it seems like I'm stuck between a rock and a hard place: the first approach it proposes (using init) is not applicable to initialization list; while in the second approach it is explicitly stated that it cannot handle the case where we need to access the instance data declared in Derived.
Calling virtual functions from a constructor or destructor is dangerous and should be avoided whenever possible. All C++ implementations should call the version of the function defined at the level of the hierarchy in the current constructor and no further.
Virtual functions in the constructors work differently. When creating an object of an derived class, the object of the base class is created first, which means that the derived class has not yet been created and the virtual function has not yet been overrided.
I think that all possible approaches to this problem are already described by the link that you provided (C++ FAQ). But I highly recommend rethinking your code.
You can apply a slightly different approach. You can make base constructor to accept parameters to initialize data fields, and then in derived class you pass the necessary arguments (even, perhaps, from virtual functions) to the base constructor using the initialization list. For example:
class A {
public:
A(int a, int b) : a_(a), b_(b) { }
virtual int getA() const = 0;
virtual int getB() const = 0;
void print() { cout << a_ << ' ' << b_ << endl; }
private:
const int a_ = 0;
const int b_ = 0;
};
class B : public A {
public:
B() : A(getA(), getB()) { }
int getA() const override { return 1; }
int getB() const override { return 2; }
};
int main() {
B b;
b.print();
return 0;
}

C++ Constructors vs Initialization Lists speed comparison

Are there any differences in execution time between constructors and initialization lists?(or is it just a matter of coding preference).
I have a set of objects that needs to be created frequently and would like to know if there is any performance gain by using initialization lists instead of constructors.
If I were to create a million instances of class A and another million of class B which choice would be better(the objects represent packets generated within a network hence these numbers).
class A {
private:
int a, b;
public:
A(int a_var, int b_var):a(a_var), b(b_var) {};
};
class B {
private:
int a, b;
public:
B(int a_var, int b_var) {
a = a_var;
b = b_var;
}
};
If any of the constructors is faster than the other for primitive types(as in the example) will it be faster if a and b were to be replaced by types?
Type example:
class AType {
private:
string a, b;
public:
AType(string a_var, string b_var):a(a_var), b(b_var) {};
};
The difference is for types with no trivial default constructor, which is called for you by compiler in your class B. Your class B is equivalent to:
class B {
private:
SleepyInt a, b;
public:
// takes at least 20s
B(int a_var, int b_var) : a(), b()
// ^^^^^^^^^^
{
a = a_var;
b = b_var;
}
};
If you do not place member variable or base class constructor in initialization list - ithe default constructor is called for them. int is basic type - its default constructor costs nothing - so no difference in your example, but for more complex types constructor+assignment might cost more than just constructing.
Some funny example, just to illustrate the difference:
class SleepyInt {
public:
SleepyInt () {
std::this_thread::sleep_for(std::chrono::milliseconds( 10000 ));
}
SleepyInt (int i) {}
SleepyInt & operator = (int i) { return *this; }
};
class A {
private:
SleepyInt a, b;
public:
A(int a_var, int b_var):a(a_var), b(b_var) {};
};
class B {
private:
SleepyInt a, b;
public:
// takes at least 20s
B(int a_var, int b_var) {
a = a_var;
b = b_var;
}
};
It is commonly accepted practice to use initialization lists as opposed to assignment in a constructor, and there's a very good reason for that.
Initialization lists can be used to initialize both POD (Plain Old Data) and user-defined types. When initializing a POD type, the effect is exactly the same as an assignment operator, meaning there is no performance difference between initialization lists or assignment in a constructor for POD types.
When we consider non-POD types things get more interesting. Before the constructor is called, constructors for the parent class and then any contained members are invoked, and by default the no-argument constructor is called. Using an initialization list you are able to choose which constructor is called.
So to answer the question, there is a performance difference, but only when initializing non-POD types.
If members are of more or less complex types, then the assignment initialization will first cause the default constructor call and then operator=, which may take longer.
There won't be a performance improvement if the types are built-in/intrinsic type.
That said:
Conclusion: All other things being equal, your code will run faster if
you use initialization lists rather than assignment.
Initialization list is benefical reference types, member class objects, or const members. Otherwise it takes more time.
Look at my test code:
#include <iostream>
#include <ctime>
using namespace std;
class A{
int a;
public:
A(int a_):a(a_){}
};
class B{
int b;
public:
B(){
}
B(int b_){
b=b_;
}
};
class C{
B b;
public:
C(int c_):b(c_){
}
};
class D{
B b;
public:
D(int d_){
b=d_;
}
};
int main()
{
clock_t start1[10], start2[10], end1[10], end2[10];
for(int j=0;j<10;j++){
start1[j]=clock();
for(int i=0;i<100000;i++){
A *newA=new A(i);
delete newA;
}
end1[j]=clock();
start2[j]=clock();
for(int i=0;i<100000;i++){
B *newB=new B(i);
delete newB;
}
end2[j]=clock();
}
double avg1=0, avg2=0;
for(int i=0;i<10;i++){
avg1+=(end1[i]-start1[i]);
avg2+=(end2[i]-start2[i]);
}
cout << avg1/avg2 << endl;
for(int j=0;j<10;j++){
start1[j]=clock();
for(int i=0;i<100000;i++){
C *newC=new C(i);
delete newC;
}
end1[j]=clock();
start2[j]=clock();
for(int i=0;i<100000;i++){
D *newD=new D(i);
delete newD;
}
end2[j]=clock();
}
avg1=avg2=0;
for(int i=0;i<10;i++){
avg1+=(end1[i]-start1[i]);
avg2+=(end2[i]-start2[i]);
}
cout << avg1/avg2 << endl;
system("pause");
return 0;
}
Example outputs like this:
1.02391
0.934741

c++ redefining types in subclasses and slicing

#include <string>
#include <iostream>
class a { public: int x;};
class b : public a {public: int x; } ;
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
The code above compiles fine in clang 3.0 and g++ 4.5. However the output is junk (--i.e., not three). Since the compiler doesn't seem to mind, how do I get the code to behave ?
Secondly, If there is some way to make the above slice / conversion to work correctly, how bad would it be if I then did the following, provided a good reason to do it exists :
class c : public a { public: uint64_t x; };
Why I am interested in these semantics.
The reason I want to do this is this. I have a two class heirachies, where one heirarchy (the parent) aggregages objects, on the same heirarchy level, from the other(the child). I use a custom container for the aggregation. I want to typedef the container in the parent class (the typedefs have the same name), and declare the container with the same name at each level of the parent.
The class heirarchies are designed to contain less information at lower levels ( the base classes hold the least), therefore slicing makes perfect sense here.
Edit:
There you go, this should clear things up.
class A { int x; };
class B : public A {int y;};
class Ap {std::vector<A> entries;};
class Bp : Ap{std::vector<B> entries;};
The child B has more members than the child class A. However, I wan't to present a uniform interface for code that is only interested in the members of class A.
There is no way to do that if you directly set b::x. a::x and b::x are two different members, and the latter hides the former.
You can still access a::x on an object of type b with static_cast<a&>(bee).x = 3, but the fundamental problem is that the values of a::x and b::x on an object of type b are not synchronized.
If you abstract access to both x members with a "property getter/setter", then you can arrange for the setter on the derived class to also update the member of the base class. Or (maybe this is more appropriate?) you can make the member of the base class protected and use it from the derived class directly, slicing as you need just before returning from the getter.
huh ! its a bit complicated no ?
why don't you use :
class a
{
virtual void set( int value ) { x = value; }
protected :
int x;
};
class b : public a
{
virtual void setA( int value ) { a::x = value; }
or
virtual void setA( int value ) { b::x = value; }
or
virtual void setA( int value ) { a::x = value; b::x = value; }
protected:
int x;
} ;
There are two ways of constructing a software design; one way is to make it so simple that there are obviously no deficiencies, and the other way is to make it so complicated that there are no obvious deficiencies. The first method is far more difficult.
C.A.R.Hoare
According to Jon's answer, Since a::x and b::x are separate variables, furthermore since b::x masks a::x, if you wanted to get the correct semantics you need to provide a copy conversion constructor. The following code does the trick.
#include <string>
#include <iostream>
class b;
class a {
public:
a();
a(const b & bee);
int x;
};
class b : public a {public: int x; } ;
a::a() {}
a::a(const b & bee)
{
x = bee.x;
}
int main()
{
b bee;
bee.x = 3;
a ay = bee;
std::cout << std::endl << ay.x << std::endl;
}
Maybe try something like this:
class A { int x; };
class B : public A {int y;};
class Ap {
public:
void Append(A *pa)
{
entries.push_back(pa);
}
A *GetA(size_t nIndex)
{
return entries.at(nIndex);
}
private:
std::vector<*A> entries;
};
class Bp : Ap
{
public:
B *GetB(size_t nIndex)
{
return dynamic_cast<B*>(GetA(nIndex));
}
};

derive problem about c++

Why I can't access base class A's a member in class B initialization list?
class A
{
public:
explicit A(int a1):a(a1)
{
}
explicit A()
{
}
public:
int a;
public:
virtual int GetA()
{
return a;
}
};
class B : public A
{
public:
explicit B(int a1):a(a1) // wrong!, I have to write a = a1 in {}. or use A(a1)
{
}
int GetA()
{
return a+1;
}
};
class C : public A
{
public:
explicit C(int a1):a(a1)
{
}
int GetA()
{
return a-1;
}
};
A's constructor runs before B's, and, implicitly or explicitly, the former construct all of A's instance, including the a member. Therefore B cannot use a constructor on a, because that field is already constructed. The notation you're trying to use indicates exactly to use a constructor on a, and at that point it's just impossible.
To build on Alex' answer, you can initialize the base class' "a" member by controlling its construction, like so:
class B : public A
{
public:
explicit B(int a1) : A(a1) { } // This initializes your inherited "a"
...
};
Note that I'm constructing the base class (capital "A") above, rather than attempting to directly initialize its inherited member (lowercase "a", drawing from your example).
To build even further on pilcrow's answer, you could easily initialize the A member like you want by overriding it in your B class:
class B : public A
{
public:
int a; // override a
explicit B(int a1) : a(a1) // works now
{
}
...
};
Though, I wouldn't necessarily recommend this ;)