Multiple and virtual inheritance C++ - c++

Full disclaimer, this is homework - not graded, just given to students so we can practice.
I'm asking for help, because we won't get an answer and I just want to know how to solve it.
What I can do is define structures B and C. Their interface has to be "like A's interface, with modifications so it works correctly".
I can't add any new methods. I also can't change anything in struct A.
This is the code:
#include <iostream>
struct A;
struct B;
struct C;
struct A {
A() {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
int main(){
C c;
}
And the desired output is:
A::A()
A::A()
B::B()
A::A()
A::A()
B::B()
A::A()
C::C()
What I tried to do so far:
First I started like this, just to check things out:
struct B : public A {
B() : A() {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
struct C : public B {
C() : B() {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
Which gave me:
A::A()
B::B()
C::C()
So I tried to get first C, then A, then B, then A (desired output from the bottom):
struct B : public virtual A {
B() : A() {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
struct C : public B, public A {
C() : A(), B() {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
But of course this didn't work. (warning: direct base ā€˜Aā€™ inaccessible in ā€˜Cā€™ due to ambiguity)
Adding virtual keyword like below gave me again C, B then A, from the bottom:
struct B : public virtual A {
B() : A() {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
struct C : public virtual A, public B {
C() : A(), B() {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
If I want to get C, then A I have to do the following (but then there will be no B)
struct C : public virtual A {
C() : A() {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
struct B : public virtual A, public C {
B() : C(), A() {
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
I also have no idea how could I get A::A() twice in a row.
I just want to understand how this should work, but if you still feel like you don't want to help me with a solution, then please leave me some tips.

I do not see a restriction in the exercise on use of class members:
struct A
{
A() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
struct B : A
{
B() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
};
struct C
: B
, A
{
C() { std::cout << __PRETTY_FUNCTION__ << "\n"; }
B b;
A a;
};
UPDATE
The desired output had changed since my first answer was posted. So previous answer had become wrong. But now you see the point - you can use composition and copy A a; to B definition and remove A inheritance from C definition.

You can do something like:
struct B : A { //inherit from A
B() {
A();
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
struct C : B { //inherit from B
C() {
B(); //anonymous B object
A(); //anonymous A object
std::cout << __PRETTY_FUNCTION__ << "\n";
}
};
Running sample

Related

How to initialize member variables before inherited classes

I'm trying to make one class which requires member variables to be initialized first. I know why this happens, but is there a way around this?
Current print order:
second
first
Wanted print order:
first
second
#include <iostream>
struct A {
A() {
std::cout << "first" << '\n';
}
};
struct B {
B() {
std::cout << "second" << '\n';
}
};
struct C : public B {
C() : a(), B() {
}
A a;
};
int main() {
C c;
return 0;
}
Stick your members that need initializing first in a struct and inherit privately from that, before B.
struct A {
A() { std::cout << "first" << '\n'; }
};
struct B {
B() { std::cout << "second" << '\n'; }
};
struct Members { A a; };
struct C : private Members, public B {
C() : Members(), B() {}
};
int main() {
C c;
}
The downside with this is that there is no way to avoid exposing the "member struct" to the outside world, but that shouldn't be a problem in practice.
In C++ base classes will be initialized before any member variables of a derived class.
The best recourse given the information you've provided is to prefer composition over inheritance:
struct A {
A() {
std::cout << "first" << '\n';
}
};
struct B {
B() {
std::cout << "second" << '\n';
}
};
struct C {
A a;
B b;
};
This will exhibit the desired behavior
Make A a needed reference for C:
#include <iostream>
struct A {
A() {
std::cout << "first" << '\n';
}
};
struct B {
B() {
std::cout << "second" << '\n';
}
};
struct C : public B {
C(const A& a) : _A(a), B() {}
const A& _A;
};
int main() {
A a;
C c(a);
return 0;
}

Not to use default constructor for virtual base class

I was looking at Understanding virtual base classes and constructor calls and I understand that the most derived class will call the top-base class default constructor directly. But is there a way not to call top-base default constructor?
One example for my problem,
#include <iostream>
#include <cstdint>
////// BEGIN LIBRARY CODE
class A
{
public:
A()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
A(int)
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
class B : virtual public A
{
public:
B()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
class C: virtual public A
{
public:
C()
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
class D: public B, public C
{
public:
D(int x) : A(x), B(), C() // ok. works as expected
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
////// END LIBRARY CODE
////// USER CODE BEGINS
class E: public D
{
public:
E() : D(42) // problem, invokes A(), not A(int)
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
E(int x) : D(x) // same problem
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
};
////// USER CODE ENDS
int main()
{
D d(1);
E e1,e2(42);
}
Output
A::A(int)
B::B()
C::C()
D::D(int)
A::A()
B::B()
C::C()
D::D(int)
E::E()
A::A()
B::B()
C::C()
D::D(int)
E::E(int)
Problem:
I want E to only care about D construction. But from the explanation in the beginning, if I don't add A::A(int) below, I will always use default constructor no matter how I update class D
E() : A(42), D(42) // works, but undesirable
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
E(int x) : A(x), D(x) // this works, but undesirable
{
std::cout << __PRETTY_FUNCTION__ << '\n';
}
In short, I don't want the user-code class E extending the library code class D to have to specify class A construction parameters so...
Is there any way it can be done by a "middle" class in the inheritance chain such as class D in my example above, to alleviate the most-derived classes from having to do so?
The constructor for the top-level class calls the constructors for all virtual bases. But that's no different from calling constructors for direct non-virtual bases: if you put in an explicit constructor call, that's what the compiler will use; if you don't, it will use the default constructor. So the answer is no, if the default constructor isn't appropriate, you can't avoid calling A's constructor from E.

Ctor-initializer for a class doesn't call to the appropriate constructor

I'm playing with construting/destructing object. Here is what I've tried http://coliru.stacked-crooked.com/a/ff17cc5649897430:
#include <iostream>
struct B{
B(){ std::cout << "B()" << std::endl; }
B(int){ std::cout << "B(int)" << std::endl; }
};
struct A : virtual B
{
int B;
A(int a) : B(a) { std::cout << "A(int)" << std::endl; }
} a(10);
int main()
{
}
The program output is
B()
A(int)
Why? I explicitly specify the constructor of the class B to be invoked in the ctor-initializer.
The B(a) is constructing the B member variable. Name your variables better and you'll see what you want to see.

Preventing redundant function calls in the presence of diamond inheritance

What's a good strategy for preventing redundant function calls in the presence of diamond inheritance? Specifically, say we have a program:
#include <iostream>
struct A {
int a;
A(int a_) : a(a_) {}
virtual void print() {
std::cout << "a: " << a << std::endl;
}
};
struct B : virtual public A {
int b;
B(int a_,int b_) : A(a_), b(b_) {}
virtual void print() {
A::print();
std::cout << "b: " << b << std::endl;
}
};
struct C : virtual public A {
int c;
C(int a_,int c_) : A(a_), c(c_) {}
virtual void print() {
A::print();
std::cout << "c: " << c << std::endl;
}
};
struct D : public B,public C {
int d;
D(int a_,int b_,int c_,int d_) : A(a_), B(a_,b_), C(a_,c_), d(d_) {}
void print() {
B::print();
C::print();
std::cout << "d: " << d << std::endl;
}
};
int main() {
D d(1,2,3,4);
d.print();
}
When we call d.print(), we get:
a: 1
b: 2
a: 1
c: 3
d: 4
where a has been printed twice. Is there a good way to prevent this? Certainly, we could manually wire the connections with a code like:
#include <iostream>
struct A {
int a;
A(int a_) : a(a_) {}
virtual void print_() {
std::cout << "a: " << a << std::endl;
}
virtual void print() {
A::print_();
}
};
struct B : virtual public A {
int b;
B(int a_,int b_) : A(a_), b(b_) {}
virtual void print_() {
std::cout << "b: " << b << std::endl;
}
virtual void print() {
A::print_();
B::print_();
}
};
struct C : virtual public A {
int c;
C(int a_,int c_) : A(a_), c(c_) {}
virtual void print_() {
std::cout << "c: " << c << std::endl;
}
virtual void print() {
A::print_();
C::print_();
}
};
struct D : public B,public C {
int d;
D(int a_,int b_,int c_,int d_) : A(a_), B(a_,b_), C(a_,c_), d(d_) {}
virtual void print_() {
std::cout << "d: " << d << std::endl;
}
virtual void print() {
A::print_();
B::print_();
C::print_();
D::print_();
}
};
int main() {
D d(1,2,3,4);
d.print();
}
which correctly outputs
a: 1
b: 2
c: 3
d: 4
but I would like to know if there's a better way. In terms of where this arises, imagine a situation with the objects A, B, C, and D are complicated and need to be able to write themselves to disk. We only want to write the output code for each A, B, C, and D once and it's important that D not write information about A twice.
<---EDIT--->
Here's two more ways of fixing the problem, but they're still kind of obtuse. The first one is from Cristian and involves setting a flag on whether or not A has been printed
#include <iostream>
struct A {
int a;
bool have_printed;
A(int a_) : have_printed(false), a(a_) {}
virtual void print() {
if(have_printed) return;
std::cout << "a: " << a << std::endl;
have_printed=true;
}
void clear() {
have_printed=false;
}
};
struct B : virtual public A {
int b;
B(int a_,int b_) : A(a_), b(b_) {}
virtual void print() {
A::print();
std::cout << "b: " << b << std::endl;
}
};
struct C : virtual public A {
int c;
C(int a_,int c_) : A(a_), c(c_) {}
virtual void print() {
A::print();
std::cout << "c: " << c << std::endl;
}
};
struct D : public B,public C {
int d;
D(int a_,int b_,int c_,int d_) : A(a_), B(a_,b_), C(a_,c_), d(d_) {}
void print() {
B::print();
C::print();
std::cout << "d: " << d << std::endl;
}
};
int main() {
D d(1,2,3,4);
d.clear();
d.print();
}
This correctly outputs. A second way is more complicated, but may allow the structure to grow. Basically, we separate out the printer from the class and then register a list of printers inside each object. When we want to print, we iterate over the list of printers, which then gives us the correct output. I feel this uses too much machinery, but I'll include in case someone else gets a better idea:
// A simple unary function. Technically, the stl version doesn't require
// the operator
template <typename A,typename B>
struct unary {
virtual B operator () (A a) {};
};
struct A {
// Data
int a;
// A list of pointers to unary functions. We need pointers to unary
// functions rather than unary functions since we need the printer
// to be polymorphic.
std::list < unary<A*,void>* > printers;
A(int a_);
// We actually end up allocating memory for the printers, which is held
// internally. Here, we free that memory.
~A() {
for(std::list < unary<A*,void>* >::iterator printer
=printers.begin();
printer != printers.end();
printer++
)
delete (*printer);
}
private:
// Require for the dynamic cast used later
virtual void ___dummy() {};
};
// Prints out the data for A
struct A_Printer : public unary<A*,void>{
void operator () (A* a) {
std::cout << "a: " << a->a << std::endl;
}
};
// Adds the printer for a to the list of printers
A::A(int a_) : a(a_) {
printers.push_back(new A_Printer());
}
// Now that the structure is setup, we just need to define the data for b,
// it's printer, and then register the printer with the rest
struct B : virtual public A {
int b;
B(int a_,int b_);
};
struct B_Printer : public unary<A*,void>{
void operator () (A* b) {
std::cout << "b: " << dynamic_cast <B*>(b)->b << std::endl;
}
};
B::B(int a_,int b_) : A(a_), b(b_) {
printers.push_back(new B_Printer());
}
// See the discussion for B
struct C : virtual public A {
int c;
C(int a_,int c_);
};
struct C_Printer : public unary<A*,void>{
void operator () (A* c) {
std::cout << "c: " << dynamic_cast <C*>(c)->c << std::endl;
}
};
C::C(int a_,int c_) : A(a_), c(c_) {
printers.push_back(new C_Printer());
}
// See the discussion for B
struct D : public B,public C {
int d;
D(int a_,int b_,int c_,int d_);
};
struct D_Printer : public unary<A*,void>{
void operator () (A* d) {
std::cout << "d: " << dynamic_cast <D*>(d)->d << std::endl;
}
};
D::D(int a_,int b_,int c_,int d_) : A(a_), B(a_,b_), C(a_,c_), d(d_) {
printers.push_back(new D_Printer());
}
// This actually prints everything. Basically, we iterate over the printers
// and call each one in term on the input.
void print(A* a) {
for(std::list < unary<A*,void>* >::iterator printer
=a->printers.begin();
printer != a->printers.end();
printer++
)
(*(*printer))(a);
}
int main() {
D d(1,2,3,4);
// This should print 1,2,3,4
print(&d);
}
<---EDIT 2--->
tmpearce had a good idea to accumulate all of the information in a hash table prior to assembling it. In this way, it's possible to check if the individual information has been created yet and prevent redundancies. I think this is a good idea when the information can be assembled easily. If this is not the case, a slight variation may work, which combines the ideas of tmpearce and Cristian. Here, we pass around a set (or hashtable, or whatever) that keeps track of whether or not a function has been called. In this way, we can check whether or not some function has been computed. It doesn't require perpetual state, so it should be safe to call multiple times:
#include <iostream>
#include <set>
struct A {
int a;
A(int a_) : a(a_) {}
virtual void print_(std::set <std::string>& computed) {
if(computed.count("A") > 0) return;
computed.insert("A");
std::cout << "a: " << a << std::endl;
}
void print() {
std::set <std::string> computed;
print_(computed);
}
};
struct B : virtual public A {
int b;
B(int a_,int b_) : A(a_), b(b_) {}
virtual void print_(std::set <std::string>& computed) {
A::print_(computed);
if(computed.count("B") > 0) return;
computed.insert("B");
std::cout << "b: " << b << std::endl;
}
};
struct C : virtual public A {
int c;
C(int a_,int c_) : A(a_), c(c_) {}
virtual void print_(std::set <std::string>& computed) {
A::print_(computed);
if(computed.count("C") > 0) return;
computed.insert("C");
std::cout << "c: " << c << std::endl;
}
};
struct D : public B,public C {
int d;
D(int a_,int b_,int c_,int d_) : A(a_), B(a_,b_), C(a_,c_), d(d_) {}
virtual void print_(std::set <std::string>& computed) {
B::print_(computed);
C::print_(computed);
if(computed.count("D") > 0) return;
computed.insert("D");
std::cout << "d: " << d << std::endl;
}
};
int main() {
D d(1,2,3,4);
d.print();
}
In any case, I'll mark this problem off as solved. Though, I'd always like to hear additional answers.
My approach would sort of combine the ones you've mentioned. I'd make the virtual method do something a bit different:
class A
{
public:
virtual void getInfo(std::map<std::string,std::string>& output)
{
if(output.count("A") == 0)
{
output["A"] = "a: 1";
}
}
void print()
{
std::map<std::string,std::string> m;
getInfo(m); //virtual method (most derived will be called)
std::map<std::string,std::string>::iterator iter = m.begin();
for(; iter!=m.end(); ++iter)
{
std::cout<<iter->second();
}
}
};
class B : public A
{
virtual void getInfo(std::map<std::string,std::string>& output)
{
A::getInfo(output);
if(output.count("B") == 0)
{
output["B"] = "b: 2";
}
}
};
print is now a non-virtual method that uses getInfo to populate a container, then iterates over it display/save the output. Each class can thus check to make sure the container doesn't already contain the desired output for that level of the inheritance chain before writing and adding the string to the container.
I'd add a private flag to A struct (and to B and C if diamond extends beyond one level) and checking it & marking it as already traversed. This would also help in more complicated (nested) diamond patterns.
Like this:
struct A {
int a;
A(int a_) : a(a_) {traversed = false;}
virtual void print() {
if (traversed) return;
std::cout << "a: " << a << std::endl;
traversed = true;
}
private:
bool traversed;
};
Only one class constructs the virtual base (the most derived, D) so I would ensure only one class prints the A object, and like its construction, make it happen first (possibly important if you're writing objects to disk.)
You could add a void* argument to A's constructor and store it in a member of A. Each derived class would construct the virtual base as A(a, this).
Add a new member function to A, do_print(void*) and have every derived class call do_print(this) instead of A::print(). The do_print(void*) function compares its argument with the stored void* passed to the A ctor and only prints if it's the same. This relies on every derived class having a distinct address, which will be true if all the classes are non-empty, but if that assumption holds it ensures only the most derived object prints the virtual base.

Redefinition of constructor with inheritance

Why in the underlying example keeps the compiler complaining about a redefinition for the B constructor. If i remove the {} it complains they need to be there. How is this done correctly?
I want to implement the constructor of B in the CPP file and not inline.
#include <vector>
#include <sstream>
#include <iostream>
using namespace std;
class A
{
public:
A();
~A();
};
class B : public A
{
public:
B() : A() {};
~B();
};
A::A()
{
cout << "A construct!";
}
B::B()
{
cout << "B construct!";
cout << "B construct!";
cout << "B construct!";
cout << "B construct!";
cout << "B construct!";
cout << "B construct!";
cout << "B construct!";
cout << "B construct!";
cout << "B construct!";
cout << "B construct!";
}
int main()
{
return 0;
}
You have already defined B constructor in the class definition:
class B : public A
{
public:
B() : A() {};
~B();
};
So, when you define it again outside of the class definition:
B::B()
{
cout << "B construct!";
you get the error; if the correct constructor is the last one, replace your class definition with this one:
class B : public A
{
public:
B();
~B();
};
If you want to specify the base class constructor in B constructor definition, you can do:
B::B()
: A()
{
cout << "B construct!";
Remove : A() {}, that's the body of your constructor, not just {}. Add the initializer list to the body B::B() you have later on.