L4 Multiple Inheritance - example code

Slide 9 - 10 Graphical Card deck example - ambiguous call - use scope resolution operator (::) as solution

#include <iostream>
using namespace std;
 
class CardDeck {
    public:
        void draw() { cout << "CardDeck.draw()" << endl;  }
};
 
class GraphicalObject {
    public:
        void draw() { cout << "GraphicalCardDeck.draw()" << endl; }
 
};
 
class GraphicalCardDeck : public CardDeck, public GraphicalObject {};
 
int main() {
    GraphicalCardDeck gcd;
    gcd.draw(); //ambiguous call - ERROR - comment this line 
 
        //solution A
        /*
        gcd.CardDeck::draw();
        gcd.GraphicalObject::draw();
    */
}

Slide 11 - Solution B1 - disambiguation using overloaded methods

No ambiguity using overloaded methods using different argument types

#include <iostream>
using namespace std;
 
class CardDeck {
    public:
        void draw() { cout << "CardDeck.draw()" << endl;  }
};
 
class GraphicalObject {
    public:
        void draw() { cout << "GraphicalCardDeck.draw()" << endl; }
 
};
 
class GraphicsContext {};
 
class GraphicalCardDeck : public CardDeck, public GraphicalObject {
    public:
        void draw() {
            CardDeck::draw();
        }
 
        void draw(GraphicsContext &gc) {
            GraphicalObject::draw();
        }
};
 
int main() {
    GraphicalCardDeck gcd;
    gcd.draw();
    GraphicsContext gc;
    gcd.draw(gc);
}

Slide 12 Solution C

#include <iostream>
using namespace std;
 
class CardDeck {
    public:
        void draw() { cout << "CardDeck.draw()" << endl;  }
};
 
class GraphicalObject {
    public:
        void draw() { cout << "GraphicalCardDeck.draw()" << endl; }
 
};
 
class GraphicsContext {};
 
class GraphicalCardDeck : public CardDeck, public GraphicalObject {
 
    public:
    using CardDeck::draw;
    //using GraphicalObject::draw;
 
    void drawCard() {
        draw();
    }
 
    void draw(GraphicsContext &gc) {
        draw();
    }
};
 
int main() {
    GraphicalCardDeck gcd;
    gcd.drawCard();
    //GraphicsContext gc;
    //gcd.draw(gc);
}

Slides 13 - using different type signatures

#include <iostream>
using namespace std;
 
class CardDeck {
    public:
        void draw() { cout << "CardDeck.draw()" << endl;  }
};
 
class GraphicalObject {
    public:
        void draw() { cout << "GraphicalCardDeck.draw()" << endl; }
 
};
 
class GraphicsContext {};
 
class GraphicalCardDeck : public CardDeck, public GraphicalObject {
    public:
        void draw() {
            CardDeck::draw();
        }
 
        void paint() {
            GraphicalObject::draw();
        }
};
 
int main() {
    GraphicalCardDeck *gcd;
    gcd->draw();
    gcd->paint();
}

Slides 14 - using different type signatures

#include <iostream>
using namespace std;
 
class CardDeck {
    public:
        virtual void draw() { cout << "CardDeck.draw()" << endl;  }
};
 
class GraphicalObject {
    public:
        virtual void draw() { cout << "GraphicalCardDeck.draw()" << endl; }
 
};
 
class GraphicsContext {};
 
class GraphicalCardDeck : public CardDeck, public GraphicalObject {
    public:
        void draw() {
            cout << "in GraphicalCardDeck.draw() " << endl;
            CardDeck::draw();
        }
 
        void paint() {
            GraphicalObject::draw();
        }
};
 
int main() {
    GraphicalObject *go = new GraphicalCardDeck();
    go->draw();
    //go->paint();
}

Slide 20 Susbstitiutability example

#include <iostream>
using namespace std;
 
class CardDeck {
    public:
        virtual void draw() { cout << "CardDeck.draw()" << endl;  }
};
 
class GraphicalObject {
    public:
        virtual void draw() { cout << "GraphicalCardDeck.draw()" << endl; }
 
};
 
class CardDeckParent : public CardDeck {
    public:
        virtual void draw() {this->cardDeckDraw(); }
        virtual void cardDeckDraw() {CardDeck::draw();}
};
 
class GraphicalObjectParent: public GraphicalObject {
    public:
        virtual void draw() {goDraw();}
        virtual void goDraw() {GraphicalObject::draw();}
};
 
class GraphicalCardDeck:public CardDeckParent,public GraphicalObjectParent {
    public:
        virtual void cardDeckDraw() {CardDeckParent::cardDeckDraw();};
        virtual void goDraw() {GraphicalObjectParent::goDraw();}
};
 
int main() {
    GraphicalCardDeck *gcd = new GraphicalCardDeck();
    CardDeck *cd = dynamic_cast<CardDeck*>(gcd); 
    GraphicalObject *go = dynamic_cast<GraphicalObject*>(gcd);
 
    cd->draw(); // ok
    go->draw(); // ok
 
    gcd->cardDeckDraw(); // ok
    gcd->goDraw(); // ok
 
    //gcd->draw(); // error - ambiguous
}

Slides 21-23 Diamond problem example

#include <iostream>
using namespace std;
 
class A {
    public:
        A() {cout << "A() called" << endl;}
        void m1() {cout << "A.m1() " << endl;}
};
 
class B : public A {};
 
class C : public A{};
 
class D : public B, public C {};
 
int main() {
    D d;
    d.m1(); //ambiguous call because there are two objects of A- compile ERROR
}

Slides 21-23 Diamond problem example solution using virtual inheritance

#include <iostream>
using namespace std;
 
class A {
    public:
        A() {cout << "A() called" << endl;}
        void m1() {cout << "A.m1() " << endl;}
};
 
class B : virtual public A {}; //using virtual inheritance
 
class C : virtual public A{}; //using virtual inheritance
 
class D : public B, public C {};
 
int main() {
    D d;
    d.m1(); //will work now because there is only one instance of A
}
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License