C++ diamond problem - How to call base method only onceWhy should I avoid multiple inheritance in C++?Can I call a constructor from another constructor (do constructor chaining) in C++?How can I profile C++ code running on Linux?Asymmetric virtual Inheritance diamond in C++How to make plugable factory work with lua?Method of derived class needs to downcast its parameterMethod resolution order in C++How to ensure that the assignment operator on a virtual base class is called only once?C++11 introduced a standardized memory model. What does it mean? And how is it going to affect C++ programming?overriding 'virtual void ' c++ errorC++ Compiler doesn't recognize templated diamond

Minor Revision with suggestion of an alternative proof by reviewer

How exactly does Hawking radiation decrease the mass of black holes?

How to creep the reader out with what seems like a normal person?

Is there an official tutorial for installing Ubuntu 18.04+ on a device with an SSD and an additional internal hard drive?

Phrase for the opposite of "foolproof"

How to have a sharp product image?

How do I deal with a coworker that keeps asking to make small superficial changes to a report, and it is seriously triggering my anxiety?

Unexpected email from Yorkshire Bank

What was the first Intel x86 processor with "Base + Index * Scale + Displacement" addressing mode?

How to pronounce 'C++' in Spanish

Does holding a wand and speaking its command word count as V/S/M spell components?

Realistic Necromancy?

What is the strongest case that can be made in favour of the UK regaining some control over fishing policy after Brexit?

How to reduce LED flash rate (frequency)

How to make a pipeline wait for end-of-file or stop after an error?

Map of water taps to fill bottles

Meaning of Bloch representation

Is it possible to determine the symmetric encryption method used by output size?

How to stop co-workers from teasing me because I know Russian?

How to solve constants out of the internal energy equation?

Please, smoke with good manners

Error message with tabularx

Why do Computer Science majors learn Calculus?

How can Republicans who favour free markets, consistently express anger when they don't like the outcome of that choice?



C++ diamond problem - How to call base method only once


Why should I avoid multiple inheritance in C++?Can I call a constructor from another constructor (do constructor chaining) in C++?How can I profile C++ code running on Linux?Asymmetric virtual Inheritance diamond in C++How to make plugable factory work with lua?Method of derived class needs to downcast its parameterMethod resolution order in C++How to ensure that the assignment operator on a virtual base class is called only once?C++11 introduced a standardized memory model. What does it mean? And how is it going to affect C++ programming?overriding 'virtual void ' c++ errorC++ Compiler doesn't recognize templated diamond






.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;








26















I'm using multiple inheritance in C++ and extending base methods by calling their base explicitly. Assume the following hierarchy:



 Creature
/
Swimmer Flier
/
Duck


Which corresponds to



class Creature

public:
virtual void print()

std::cout << "I'm a creature" << std::endl;

;

class Swimmer : public virtual Creature

public:
void print()

Creature::print();
std::cout << "I can swim" << std::endl;

;

class Flier : public virtual Creature

public:
void print()

Creature::print();
std::cout << "I can fly" << std::endl;

;

class Duck : public Flier, public Swimmer

public:
void print()

Flier::print();
Swimmer::print();
std::cout << "I'm a duck" << std::endl;

;


Now this presents a problem - calling the duck's print method calls its respective base methods, all of which in turn call the Creature::print() method, so it ends up being called twice-



I'm a creature
I can fly
I'm a creature
I can swim
I'm a duck


I would like to find a way to make sure the base method is called only once. Something similar to the way virtual inheritance works (calling the base constructor on the first call, then only assigning a pointer to it on successive calls from other derived classes).



Is there some built-in way to do this or do we need to resort to implementing one ourselves?



If so, how would you approach this?



The question isn't specific to printing. I wondered if there's a mechanism for extending base methods and functionality while keeping the call order and avoiding the diamond problem.



I understand now that the most prominent solution would be to add helper methods, but I just wondered if there's a "cleaner" way.










share|improve this question



















  • 16





    Both Flier and Swimmer's print explicitly calls Creature's print. If I were you I would make an attempt to solve the problem without this inheritance. "Composition over inheritance." For example ECS (entity component system) is exactly about to put properties together in a flexible way without the inheritance hell.

    – titapo
    Apr 24 at 12:23






  • 2





    add (protected)method to your extra std::cout, so you can choose which version to call exactly.

    – Jarod42
    Apr 24 at 12:24






  • 1





    @titapo that is a good suggestion, please post it as an answer instead of a comment.

    – Captain Man
    Apr 24 at 19:24






  • 1





    As other people posted solutions already, I'd like to emphasize here, that you do not really want to use multiple inheritance and especially a diamond inheritance at all: stackoverflow.com/questions/406081/…

    – Lukas Plazovnik
    Apr 24 at 20:24











  • I use multiple inheritances ALL the time professionally. It's not a bad thing, just that most people don't understand the repercussions of multiple inheritances and how to avoid digging yourself into a hole. It's wonderful for MVC and all manner of GUI stuff!

    – Bill Smith
    2 days ago

















26















I'm using multiple inheritance in C++ and extending base methods by calling their base explicitly. Assume the following hierarchy:



 Creature
/
Swimmer Flier
/
Duck


Which corresponds to



class Creature

public:
virtual void print()

std::cout << "I'm a creature" << std::endl;

;

class Swimmer : public virtual Creature

public:
void print()

Creature::print();
std::cout << "I can swim" << std::endl;

;

class Flier : public virtual Creature

public:
void print()

Creature::print();
std::cout << "I can fly" << std::endl;

;

class Duck : public Flier, public Swimmer

public:
void print()

Flier::print();
Swimmer::print();
std::cout << "I'm a duck" << std::endl;

;


Now this presents a problem - calling the duck's print method calls its respective base methods, all of which in turn call the Creature::print() method, so it ends up being called twice-



I'm a creature
I can fly
I'm a creature
I can swim
I'm a duck


I would like to find a way to make sure the base method is called only once. Something similar to the way virtual inheritance works (calling the base constructor on the first call, then only assigning a pointer to it on successive calls from other derived classes).



Is there some built-in way to do this or do we need to resort to implementing one ourselves?



If so, how would you approach this?



The question isn't specific to printing. I wondered if there's a mechanism for extending base methods and functionality while keeping the call order and avoiding the diamond problem.



I understand now that the most prominent solution would be to add helper methods, but I just wondered if there's a "cleaner" way.










share|improve this question



















  • 16





    Both Flier and Swimmer's print explicitly calls Creature's print. If I were you I would make an attempt to solve the problem without this inheritance. "Composition over inheritance." For example ECS (entity component system) is exactly about to put properties together in a flexible way without the inheritance hell.

    – titapo
    Apr 24 at 12:23






  • 2





    add (protected)method to your extra std::cout, so you can choose which version to call exactly.

    – Jarod42
    Apr 24 at 12:24






  • 1





    @titapo that is a good suggestion, please post it as an answer instead of a comment.

    – Captain Man
    Apr 24 at 19:24






  • 1





    As other people posted solutions already, I'd like to emphasize here, that you do not really want to use multiple inheritance and especially a diamond inheritance at all: stackoverflow.com/questions/406081/…

    – Lukas Plazovnik
    Apr 24 at 20:24











  • I use multiple inheritances ALL the time professionally. It's not a bad thing, just that most people don't understand the repercussions of multiple inheritances and how to avoid digging yourself into a hole. It's wonderful for MVC and all manner of GUI stuff!

    – Bill Smith
    2 days ago













26












26








26


7






I'm using multiple inheritance in C++ and extending base methods by calling their base explicitly. Assume the following hierarchy:



 Creature
/
Swimmer Flier
/
Duck


Which corresponds to



class Creature

public:
virtual void print()

std::cout << "I'm a creature" << std::endl;

;

class Swimmer : public virtual Creature

public:
void print()

Creature::print();
std::cout << "I can swim" << std::endl;

;

class Flier : public virtual Creature

public:
void print()

Creature::print();
std::cout << "I can fly" << std::endl;

;

class Duck : public Flier, public Swimmer

public:
void print()

Flier::print();
Swimmer::print();
std::cout << "I'm a duck" << std::endl;

;


Now this presents a problem - calling the duck's print method calls its respective base methods, all of which in turn call the Creature::print() method, so it ends up being called twice-



I'm a creature
I can fly
I'm a creature
I can swim
I'm a duck


I would like to find a way to make sure the base method is called only once. Something similar to the way virtual inheritance works (calling the base constructor on the first call, then only assigning a pointer to it on successive calls from other derived classes).



Is there some built-in way to do this or do we need to resort to implementing one ourselves?



If so, how would you approach this?



The question isn't specific to printing. I wondered if there's a mechanism for extending base methods and functionality while keeping the call order and avoiding the diamond problem.



I understand now that the most prominent solution would be to add helper methods, but I just wondered if there's a "cleaner" way.










share|improve this question
















I'm using multiple inheritance in C++ and extending base methods by calling their base explicitly. Assume the following hierarchy:



 Creature
/
Swimmer Flier
/
Duck


Which corresponds to



class Creature

public:
virtual void print()

std::cout << "I'm a creature" << std::endl;

;

class Swimmer : public virtual Creature

public:
void print()

Creature::print();
std::cout << "I can swim" << std::endl;

;

class Flier : public virtual Creature

public:
void print()

Creature::print();
std::cout << "I can fly" << std::endl;

;

class Duck : public Flier, public Swimmer

public:
void print()

Flier::print();
Swimmer::print();
std::cout << "I'm a duck" << std::endl;

;


Now this presents a problem - calling the duck's print method calls its respective base methods, all of which in turn call the Creature::print() method, so it ends up being called twice-



I'm a creature
I can fly
I'm a creature
I can swim
I'm a duck


I would like to find a way to make sure the base method is called only once. Something similar to the way virtual inheritance works (calling the base constructor on the first call, then only assigning a pointer to it on successive calls from other derived classes).



Is there some built-in way to do this or do we need to resort to implementing one ourselves?



If so, how would you approach this?



The question isn't specific to printing. I wondered if there's a mechanism for extending base methods and functionality while keeping the call order and avoiding the diamond problem.



I understand now that the most prominent solution would be to add helper methods, but I just wondered if there's a "cleaner" way.







c++ multiple-inheritance diamond-problem






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 2 days ago









Peter Mortensen

14k1987114




14k1987114










asked Apr 24 at 12:14









O. AroestiO. Aroesti

177312




177312







  • 16





    Both Flier and Swimmer's print explicitly calls Creature's print. If I were you I would make an attempt to solve the problem without this inheritance. "Composition over inheritance." For example ECS (entity component system) is exactly about to put properties together in a flexible way without the inheritance hell.

    – titapo
    Apr 24 at 12:23






  • 2





    add (protected)method to your extra std::cout, so you can choose which version to call exactly.

    – Jarod42
    Apr 24 at 12:24






  • 1





    @titapo that is a good suggestion, please post it as an answer instead of a comment.

    – Captain Man
    Apr 24 at 19:24






  • 1





    As other people posted solutions already, I'd like to emphasize here, that you do not really want to use multiple inheritance and especially a diamond inheritance at all: stackoverflow.com/questions/406081/…

    – Lukas Plazovnik
    Apr 24 at 20:24











  • I use multiple inheritances ALL the time professionally. It's not a bad thing, just that most people don't understand the repercussions of multiple inheritances and how to avoid digging yourself into a hole. It's wonderful for MVC and all manner of GUI stuff!

    – Bill Smith
    2 days ago












  • 16





    Both Flier and Swimmer's print explicitly calls Creature's print. If I were you I would make an attempt to solve the problem without this inheritance. "Composition over inheritance." For example ECS (entity component system) is exactly about to put properties together in a flexible way without the inheritance hell.

    – titapo
    Apr 24 at 12:23






  • 2





    add (protected)method to your extra std::cout, so you can choose which version to call exactly.

    – Jarod42
    Apr 24 at 12:24






  • 1





    @titapo that is a good suggestion, please post it as an answer instead of a comment.

    – Captain Man
    Apr 24 at 19:24






  • 1





    As other people posted solutions already, I'd like to emphasize here, that you do not really want to use multiple inheritance and especially a diamond inheritance at all: stackoverflow.com/questions/406081/…

    – Lukas Plazovnik
    Apr 24 at 20:24











  • I use multiple inheritances ALL the time professionally. It's not a bad thing, just that most people don't understand the repercussions of multiple inheritances and how to avoid digging yourself into a hole. It's wonderful for MVC and all manner of GUI stuff!

    – Bill Smith
    2 days ago







16




16





Both Flier and Swimmer's print explicitly calls Creature's print. If I were you I would make an attempt to solve the problem without this inheritance. "Composition over inheritance." For example ECS (entity component system) is exactly about to put properties together in a flexible way without the inheritance hell.

– titapo
Apr 24 at 12:23





Both Flier and Swimmer's print explicitly calls Creature's print. If I were you I would make an attempt to solve the problem without this inheritance. "Composition over inheritance." For example ECS (entity component system) is exactly about to put properties together in a flexible way without the inheritance hell.

– titapo
Apr 24 at 12:23




2




2





add (protected)method to your extra std::cout, so you can choose which version to call exactly.

– Jarod42
Apr 24 at 12:24





add (protected)method to your extra std::cout, so you can choose which version to call exactly.

– Jarod42
Apr 24 at 12:24




1




1





@titapo that is a good suggestion, please post it as an answer instead of a comment.

– Captain Man
Apr 24 at 19:24





@titapo that is a good suggestion, please post it as an answer instead of a comment.

– Captain Man
Apr 24 at 19:24




1




1





As other people posted solutions already, I'd like to emphasize here, that you do not really want to use multiple inheritance and especially a diamond inheritance at all: stackoverflow.com/questions/406081/…

– Lukas Plazovnik
Apr 24 at 20:24





As other people posted solutions already, I'd like to emphasize here, that you do not really want to use multiple inheritance and especially a diamond inheritance at all: stackoverflow.com/questions/406081/…

– Lukas Plazovnik
Apr 24 at 20:24













I use multiple inheritances ALL the time professionally. It's not a bad thing, just that most people don't understand the repercussions of multiple inheritances and how to avoid digging yourself into a hole. It's wonderful for MVC and all manner of GUI stuff!

– Bill Smith
2 days ago





I use multiple inheritances ALL the time professionally. It's not a bad thing, just that most people don't understand the repercussions of multiple inheritances and how to avoid digging yourself into a hole. It's wonderful for MVC and all manner of GUI stuff!

– Bill Smith
2 days ago












7 Answers
7






active

oldest

votes


















36














Most likely this is an XY problem. But ... just don't call it twice.



#include <iostream>

class Creature

public:
virtual void identify()

std::cout << "I'm a creature" << std::endl;

;

class Swimmer : public virtual Creature

public:
virtual void identify() override

Creature::identify();
tell_ability();
std::cout << "I'm a swimmern";


virtual void tell_ability()

std::cout << "I can swimn";

;

class Flier : public virtual Creature

public:
virtual void identify() override

Creature::identify();
tell_ability();
std::cout << "I'm a fliern";


virtual void tell_ability()

std::cout << "I can flyn";

;

class Duck : public Flier, public Swimmer

public:
virtual void tell_ability() override

Flier::tell_ability();
Swimmer::tell_ability();


virtual void identify() override

Creature::identify();
tell_ability();
std::cout << "I'm a duckn";

;

int main()

Creature c;
c.identify();
std::cout << "------------------n";

Swimmer s;
s.identify();
std::cout << "------------------n";

Flier f;
f.identify();
std::cout << "------------------n";

Duck d;
d.identify();
std::cout << "------------------n";



Output:



I'm a creature
------------------
I'm a creature
I can swim
I'm a swimmer
------------------
I'm a creature
I can fly
I'm a flier
------------------
I'm a creature
I can fly
I can swim
I'm a duck
------------------





share|improve this answer
































    17














    We can let the base class keep track of the attributes:



    #include <iostream>
    #include <string>
    #include <vector>

    using namespace std::string_literals;

    class Creature

    public:
    std::string const attribute"I'm a creature"s;
    std::vector<std::string> attributesattribute;
    virtual void print()

    for (auto& i : attributes)
    std::cout << i << std::endl;

    ;

    class Swimmer : public virtual Creature

    public:
    Swimmer() attributes.push_back(attribute);
    std::string const attribute"I can swim"s;
    ;

    class Flier : public virtual Creature

    public:
    Flier() attributes.push_back(attribute);
    std::string const attribute"I can fly"s;
    ;

    class Duck : public Flier, public Swimmer

    public:
    Duck() attributes.push_back(attribute);
    std::string const attribute"I'm a duck"s;
    ;

    int main()

    Duck d;
    d.print();




    Likewise, if it is not just printing we're after, but rather the function calls, then we could let the base class keep track of the functions:



    #include <iostream>
    #include <functional>
    #include <vector>

    class Creature

    public:
    std::vector<std::function<void()>> print_functions[this] Creature::print_this(); ;
    virtual void print_this()

    std::cout << "I'm a creature" << std::endl;

    void print()

    for (auto& f : print_functions)
    f();

    ;

    class Swimmer : public virtual Creature

    public:
    Swimmer() print_functions.push_back([this] Swimmer::print_this(); );
    void print_this()

    std::cout << "I can swim" << std::endl;

    ;

    class Flier : public virtual Creature

    public:
    Flier() print_functions.push_back([this] Flier::print_this(); );
    void print_this()

    std::cout << "I can fly" << std::endl;

    ;

    class Duck : public Flier, public Swimmer

    public:
    Duck() print_functions.push_back([this] Duck::print_this(); );
    void print_this()

    std::cout << "I'm a duck" << std::endl;

    ;

    int main()

    Duck d;
    d.print();






    share|improve this answer




















    • 1





      That makes every instance allocate an entire std::vector, which is a bit heavy.

      – Kevin
      Apr 24 at 19:35






    • 6





      @Kevin I'm guessing you won't like vtables either. :)

      – wally
      2 days ago











    • @wally vtables involve storing a pointer to a bit of read-only memory - can often be done in a single move instruction. Vectors involve allocating memory from the heap, which is going to involve grabbing and releasing a mutex, with all the memory barrier and cache-flushing that implies.

      – Martin Bonner
      2 days ago






    • 1





      @MartinBonner Other threads wouldn't have access to the object until after construction. Why would you need to lock a mutex for the vector? And where did you hear that you need a mutex for heap allocation?

      – wally
      2 days ago






    • 1





      @MartinBonner If you're referring to the locking that the operating system does then it is unavoidable. I suppose that if you create the vector with the correct size then the extra malloc might be optimized away if you're creating the entire object on the heap anyway. The contention between threads might also be reduced if the OS decided to use separate arenas for the allocations. The OS might also not be using a mutex. In general, defensively designing around this would be impractical. std::vector is not that bad.

      – wally
      2 days ago


















    6














    An easy way is to create a bunch of helper classes that mimick the inheritance structure of your main hierarchy and do all the printing in their constructors.



     struct CreaturePrinter 
    CreaturePrinter()
    std::cout << "I'm a creaturen";

    ;

    struct FlierPrinter: virtual CreaturePrinter ...
    struct SwimmerPrinter: virtual CreaturePrinter ...
    struct DuckPrinter: FlierPrinter, SwimmerPrinter ...


    Then each print method in the main hierarchy just creates the corresponding helper class. No manual chaining.



    For maintainability you can make each printer class nested in its corresponding main class.



    Naturally in most real world cases you want to pass a reference to the main object as an argument to the constructor of its helper.






    share|improve this answer
































      4














      Your explicit calls to the print methods form the crux of the issue.



      One way round this would be to drop the print calls, and replace them with say



      void queue(std::set<std::string>& data)


      and you accumulate the print messages into the set. Then it doesn't matter those functions in the hierarchy get called more than once.



      You then implement the printing of the set in a single method in Creature.



      If you want to preserve the order of printing, then you'd need to replace the set with another container that respects the order of insertion and rejects duplicates.






      share|improve this answer




















      • 2





        this doesn't solve the problem in general

        – sudo rm -rf slash
        Apr 24 at 16:29


















      4














      If you want that middle class method, do not call the base class method. The easiest and simplest way is to extract extra methods, and then reimplementing Print is easy.



      class Creature

      public:
      virtual void print()

      std::cout << "I'm a creature" << std::endl;

      ;

      class Swimmer : public virtual Creature

      public:
      void print()

      Creature::print();
      detailPrint();


      void detailPrint()

      std::cout << "I can swim" << std::endl;

      ;

      class Flier : public virtual Creature

      public:
      void print()

      Creature::print();
      detailPrint();


      void detailPrint()

      std::cout << "I can fly" << std::endl;

      ;

      class Duck : public Flier, public Swimmer

      public:
      void print()

      Creature::Print();
      Flier::detailPrint();
      Swimmer::detailPrint();
      detailPrint();


      void detailPrint()

      std::cout << "I'm a duck" << std::endl;

      ;


      Without details what is your actual problem is, it hard to come up with a better solution.






      share|improve this answer
































        2














        Use:



        template<typename Base, typename Derived>
        bool is_dominant_descendant(Derived * x)
        return std::abs(
        std::distance(
        static_cast<char*>(static_cast<void*>(x)),
        static_cast<char*>(static_cast<void*>(dynamic_cast<Base*>(x)))
        )
        ) <= sizeof(Derived);
        ;

        class Creature

        public:
        virtual void print()

        std::cout << "I'm a creature" << std::endl;

        ;

        class Walker : public virtual Creature

        public:
        void print()

        if (is_dominant_descendant<Creature>(this))
        Creature::print();
        std::cout << "I can walk" << std::endl;

        ;

        class Swimmer : public virtual Creature

        public:
        void print()

        if (is_dominant_descendant<Creature>(this))
        Creature::print();
        std::cout << "I can swim" << std::endl;

        ;

        class Flier : public virtual Creature

        public:
        void print()

        if (is_dominant_descendant<Creature>(this))
        Creature::print();
        std::cout << "I can fly" << std::endl;

        ;

        class Duck : public Flier, public Swimmer, public Walker

        public:
        void print()

        Walker::print();
        Swimmer::print();
        Flier::print();
        std::cout << "I'm a duck" << std::endl;

        ;


        And with Visual Studio 2015 the output is:



        I'm a creature
        I can walk
        I can swim
        I can fly
        I'm a duck


        But is_dominant_descendant does not have a portable definition. I wish it were a standard concept.






        share|improve this answer
































          1














          You are asking for something like inheritance on a function level that automatically calls the inherited function and just adds more code. Also you want it to be done in a virtual way just like class inheritance. Pseudo syntax:



          class Swimmer : public virtual Creature

          public:
          // Virtually inherit from Creature::print and extend it by another line of code
          void print() : virtual Creature::print()

          std::cout << "I can swim" << std::endl;

          ;

          class Flier : public virtual Creature

          public:
          // Virtually inherit from Creature::print and extend it by another line of code
          void print() : virtual Creature::print()

          std::cout << "I can fly" << std::endl;

          ;

          class Duck : public Flier, public Swimmer

          public:
          // Inherit from both prints. As they were created using "virtual function inheritance",
          // this will "mix" them just like in virtual class inheritance
          void print() : Flier::print(), Swimmer::print()

          std::cout << "I'm a duck" << std::endl;

          ;


          So the answer to your question




          Is there some built-in way to do this?




          is no. Something like this does not exist in C++. Also, I'm not aware of any other language that has something like this. But it is an interesting idea...






          share|improve this answer

























            Your Answer






            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "1"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader:
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            ,
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );













            draft saved

            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55829798%2fc-diamond-problem-how-to-call-base-method-only-once%23new-answer', 'question_page');

            );

            Post as a guest















            Required, but never shown

























            7 Answers
            7






            active

            oldest

            votes








            7 Answers
            7






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            36














            Most likely this is an XY problem. But ... just don't call it twice.



            #include <iostream>

            class Creature

            public:
            virtual void identify()

            std::cout << "I'm a creature" << std::endl;

            ;

            class Swimmer : public virtual Creature

            public:
            virtual void identify() override

            Creature::identify();
            tell_ability();
            std::cout << "I'm a swimmern";


            virtual void tell_ability()

            std::cout << "I can swimn";

            ;

            class Flier : public virtual Creature

            public:
            virtual void identify() override

            Creature::identify();
            tell_ability();
            std::cout << "I'm a fliern";


            virtual void tell_ability()

            std::cout << "I can flyn";

            ;

            class Duck : public Flier, public Swimmer

            public:
            virtual void tell_ability() override

            Flier::tell_ability();
            Swimmer::tell_ability();


            virtual void identify() override

            Creature::identify();
            tell_ability();
            std::cout << "I'm a duckn";

            ;

            int main()

            Creature c;
            c.identify();
            std::cout << "------------------n";

            Swimmer s;
            s.identify();
            std::cout << "------------------n";

            Flier f;
            f.identify();
            std::cout << "------------------n";

            Duck d;
            d.identify();
            std::cout << "------------------n";



            Output:



            I'm a creature
            ------------------
            I'm a creature
            I can swim
            I'm a swimmer
            ------------------
            I'm a creature
            I can fly
            I'm a flier
            ------------------
            I'm a creature
            I can fly
            I can swim
            I'm a duck
            ------------------





            share|improve this answer





























              36














              Most likely this is an XY problem. But ... just don't call it twice.



              #include <iostream>

              class Creature

              public:
              virtual void identify()

              std::cout << "I'm a creature" << std::endl;

              ;

              class Swimmer : public virtual Creature

              public:
              virtual void identify() override

              Creature::identify();
              tell_ability();
              std::cout << "I'm a swimmern";


              virtual void tell_ability()

              std::cout << "I can swimn";

              ;

              class Flier : public virtual Creature

              public:
              virtual void identify() override

              Creature::identify();
              tell_ability();
              std::cout << "I'm a fliern";


              virtual void tell_ability()

              std::cout << "I can flyn";

              ;

              class Duck : public Flier, public Swimmer

              public:
              virtual void tell_ability() override

              Flier::tell_ability();
              Swimmer::tell_ability();


              virtual void identify() override

              Creature::identify();
              tell_ability();
              std::cout << "I'm a duckn";

              ;

              int main()

              Creature c;
              c.identify();
              std::cout << "------------------n";

              Swimmer s;
              s.identify();
              std::cout << "------------------n";

              Flier f;
              f.identify();
              std::cout << "------------------n";

              Duck d;
              d.identify();
              std::cout << "------------------n";



              Output:



              I'm a creature
              ------------------
              I'm a creature
              I can swim
              I'm a swimmer
              ------------------
              I'm a creature
              I can fly
              I'm a flier
              ------------------
              I'm a creature
              I can fly
              I can swim
              I'm a duck
              ------------------





              share|improve this answer



























                36












                36








                36







                Most likely this is an XY problem. But ... just don't call it twice.



                #include <iostream>

                class Creature

                public:
                virtual void identify()

                std::cout << "I'm a creature" << std::endl;

                ;

                class Swimmer : public virtual Creature

                public:
                virtual void identify() override

                Creature::identify();
                tell_ability();
                std::cout << "I'm a swimmern";


                virtual void tell_ability()

                std::cout << "I can swimn";

                ;

                class Flier : public virtual Creature

                public:
                virtual void identify() override

                Creature::identify();
                tell_ability();
                std::cout << "I'm a fliern";


                virtual void tell_ability()

                std::cout << "I can flyn";

                ;

                class Duck : public Flier, public Swimmer

                public:
                virtual void tell_ability() override

                Flier::tell_ability();
                Swimmer::tell_ability();


                virtual void identify() override

                Creature::identify();
                tell_ability();
                std::cout << "I'm a duckn";

                ;

                int main()

                Creature c;
                c.identify();
                std::cout << "------------------n";

                Swimmer s;
                s.identify();
                std::cout << "------------------n";

                Flier f;
                f.identify();
                std::cout << "------------------n";

                Duck d;
                d.identify();
                std::cout << "------------------n";



                Output:



                I'm a creature
                ------------------
                I'm a creature
                I can swim
                I'm a swimmer
                ------------------
                I'm a creature
                I can fly
                I'm a flier
                ------------------
                I'm a creature
                I can fly
                I can swim
                I'm a duck
                ------------------





                share|improve this answer















                Most likely this is an XY problem. But ... just don't call it twice.



                #include <iostream>

                class Creature

                public:
                virtual void identify()

                std::cout << "I'm a creature" << std::endl;

                ;

                class Swimmer : public virtual Creature

                public:
                virtual void identify() override

                Creature::identify();
                tell_ability();
                std::cout << "I'm a swimmern";


                virtual void tell_ability()

                std::cout << "I can swimn";

                ;

                class Flier : public virtual Creature

                public:
                virtual void identify() override

                Creature::identify();
                tell_ability();
                std::cout << "I'm a fliern";


                virtual void tell_ability()

                std::cout << "I can flyn";

                ;

                class Duck : public Flier, public Swimmer

                public:
                virtual void tell_ability() override

                Flier::tell_ability();
                Swimmer::tell_ability();


                virtual void identify() override

                Creature::identify();
                tell_ability();
                std::cout << "I'm a duckn";

                ;

                int main()

                Creature c;
                c.identify();
                std::cout << "------------------n";

                Swimmer s;
                s.identify();
                std::cout << "------------------n";

                Flier f;
                f.identify();
                std::cout << "------------------n";

                Duck d;
                d.identify();
                std::cout << "------------------n";



                Output:



                I'm a creature
                ------------------
                I'm a creature
                I can swim
                I'm a swimmer
                ------------------
                I'm a creature
                I can fly
                I'm a flier
                ------------------
                I'm a creature
                I can fly
                I can swim
                I'm a duck
                ------------------






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited 2 days ago









                Peter Mortensen

                14k1987114




                14k1987114










                answered Apr 24 at 12:29









                SwordfishSwordfish

                10.7k11538




                10.7k11538























                    17














                    We can let the base class keep track of the attributes:



                    #include <iostream>
                    #include <string>
                    #include <vector>

                    using namespace std::string_literals;

                    class Creature

                    public:
                    std::string const attribute"I'm a creature"s;
                    std::vector<std::string> attributesattribute;
                    virtual void print()

                    for (auto& i : attributes)
                    std::cout << i << std::endl;

                    ;

                    class Swimmer : public virtual Creature

                    public:
                    Swimmer() attributes.push_back(attribute);
                    std::string const attribute"I can swim"s;
                    ;

                    class Flier : public virtual Creature

                    public:
                    Flier() attributes.push_back(attribute);
                    std::string const attribute"I can fly"s;
                    ;

                    class Duck : public Flier, public Swimmer

                    public:
                    Duck() attributes.push_back(attribute);
                    std::string const attribute"I'm a duck"s;
                    ;

                    int main()

                    Duck d;
                    d.print();




                    Likewise, if it is not just printing we're after, but rather the function calls, then we could let the base class keep track of the functions:



                    #include <iostream>
                    #include <functional>
                    #include <vector>

                    class Creature

                    public:
                    std::vector<std::function<void()>> print_functions[this] Creature::print_this(); ;
                    virtual void print_this()

                    std::cout << "I'm a creature" << std::endl;

                    void print()

                    for (auto& f : print_functions)
                    f();

                    ;

                    class Swimmer : public virtual Creature

                    public:
                    Swimmer() print_functions.push_back([this] Swimmer::print_this(); );
                    void print_this()

                    std::cout << "I can swim" << std::endl;

                    ;

                    class Flier : public virtual Creature

                    public:
                    Flier() print_functions.push_back([this] Flier::print_this(); );
                    void print_this()

                    std::cout << "I can fly" << std::endl;

                    ;

                    class Duck : public Flier, public Swimmer

                    public:
                    Duck() print_functions.push_back([this] Duck::print_this(); );
                    void print_this()

                    std::cout << "I'm a duck" << std::endl;

                    ;

                    int main()

                    Duck d;
                    d.print();






                    share|improve this answer




















                    • 1





                      That makes every instance allocate an entire std::vector, which is a bit heavy.

                      – Kevin
                      Apr 24 at 19:35






                    • 6





                      @Kevin I'm guessing you won't like vtables either. :)

                      – wally
                      2 days ago











                    • @wally vtables involve storing a pointer to a bit of read-only memory - can often be done in a single move instruction. Vectors involve allocating memory from the heap, which is going to involve grabbing and releasing a mutex, with all the memory barrier and cache-flushing that implies.

                      – Martin Bonner
                      2 days ago






                    • 1





                      @MartinBonner Other threads wouldn't have access to the object until after construction. Why would you need to lock a mutex for the vector? And where did you hear that you need a mutex for heap allocation?

                      – wally
                      2 days ago






                    • 1





                      @MartinBonner If you're referring to the locking that the operating system does then it is unavoidable. I suppose that if you create the vector with the correct size then the extra malloc might be optimized away if you're creating the entire object on the heap anyway. The contention between threads might also be reduced if the OS decided to use separate arenas for the allocations. The OS might also not be using a mutex. In general, defensively designing around this would be impractical. std::vector is not that bad.

                      – wally
                      2 days ago















                    17














                    We can let the base class keep track of the attributes:



                    #include <iostream>
                    #include <string>
                    #include <vector>

                    using namespace std::string_literals;

                    class Creature

                    public:
                    std::string const attribute"I'm a creature"s;
                    std::vector<std::string> attributesattribute;
                    virtual void print()

                    for (auto& i : attributes)
                    std::cout << i << std::endl;

                    ;

                    class Swimmer : public virtual Creature

                    public:
                    Swimmer() attributes.push_back(attribute);
                    std::string const attribute"I can swim"s;
                    ;

                    class Flier : public virtual Creature

                    public:
                    Flier() attributes.push_back(attribute);
                    std::string const attribute"I can fly"s;
                    ;

                    class Duck : public Flier, public Swimmer

                    public:
                    Duck() attributes.push_back(attribute);
                    std::string const attribute"I'm a duck"s;
                    ;

                    int main()

                    Duck d;
                    d.print();




                    Likewise, if it is not just printing we're after, but rather the function calls, then we could let the base class keep track of the functions:



                    #include <iostream>
                    #include <functional>
                    #include <vector>

                    class Creature

                    public:
                    std::vector<std::function<void()>> print_functions[this] Creature::print_this(); ;
                    virtual void print_this()

                    std::cout << "I'm a creature" << std::endl;

                    void print()

                    for (auto& f : print_functions)
                    f();

                    ;

                    class Swimmer : public virtual Creature

                    public:
                    Swimmer() print_functions.push_back([this] Swimmer::print_this(); );
                    void print_this()

                    std::cout << "I can swim" << std::endl;

                    ;

                    class Flier : public virtual Creature

                    public:
                    Flier() print_functions.push_back([this] Flier::print_this(); );
                    void print_this()

                    std::cout << "I can fly" << std::endl;

                    ;

                    class Duck : public Flier, public Swimmer

                    public:
                    Duck() print_functions.push_back([this] Duck::print_this(); );
                    void print_this()

                    std::cout << "I'm a duck" << std::endl;

                    ;

                    int main()

                    Duck d;
                    d.print();






                    share|improve this answer




















                    • 1





                      That makes every instance allocate an entire std::vector, which is a bit heavy.

                      – Kevin
                      Apr 24 at 19:35






                    • 6





                      @Kevin I'm guessing you won't like vtables either. :)

                      – wally
                      2 days ago











                    • @wally vtables involve storing a pointer to a bit of read-only memory - can often be done in a single move instruction. Vectors involve allocating memory from the heap, which is going to involve grabbing and releasing a mutex, with all the memory barrier and cache-flushing that implies.

                      – Martin Bonner
                      2 days ago






                    • 1





                      @MartinBonner Other threads wouldn't have access to the object until after construction. Why would you need to lock a mutex for the vector? And where did you hear that you need a mutex for heap allocation?

                      – wally
                      2 days ago






                    • 1





                      @MartinBonner If you're referring to the locking that the operating system does then it is unavoidable. I suppose that if you create the vector with the correct size then the extra malloc might be optimized away if you're creating the entire object on the heap anyway. The contention between threads might also be reduced if the OS decided to use separate arenas for the allocations. The OS might also not be using a mutex. In general, defensively designing around this would be impractical. std::vector is not that bad.

                      – wally
                      2 days ago













                    17












                    17








                    17







                    We can let the base class keep track of the attributes:



                    #include <iostream>
                    #include <string>
                    #include <vector>

                    using namespace std::string_literals;

                    class Creature

                    public:
                    std::string const attribute"I'm a creature"s;
                    std::vector<std::string> attributesattribute;
                    virtual void print()

                    for (auto& i : attributes)
                    std::cout << i << std::endl;

                    ;

                    class Swimmer : public virtual Creature

                    public:
                    Swimmer() attributes.push_back(attribute);
                    std::string const attribute"I can swim"s;
                    ;

                    class Flier : public virtual Creature

                    public:
                    Flier() attributes.push_back(attribute);
                    std::string const attribute"I can fly"s;
                    ;

                    class Duck : public Flier, public Swimmer

                    public:
                    Duck() attributes.push_back(attribute);
                    std::string const attribute"I'm a duck"s;
                    ;

                    int main()

                    Duck d;
                    d.print();




                    Likewise, if it is not just printing we're after, but rather the function calls, then we could let the base class keep track of the functions:



                    #include <iostream>
                    #include <functional>
                    #include <vector>

                    class Creature

                    public:
                    std::vector<std::function<void()>> print_functions[this] Creature::print_this(); ;
                    virtual void print_this()

                    std::cout << "I'm a creature" << std::endl;

                    void print()

                    for (auto& f : print_functions)
                    f();

                    ;

                    class Swimmer : public virtual Creature

                    public:
                    Swimmer() print_functions.push_back([this] Swimmer::print_this(); );
                    void print_this()

                    std::cout << "I can swim" << std::endl;

                    ;

                    class Flier : public virtual Creature

                    public:
                    Flier() print_functions.push_back([this] Flier::print_this(); );
                    void print_this()

                    std::cout << "I can fly" << std::endl;

                    ;

                    class Duck : public Flier, public Swimmer

                    public:
                    Duck() print_functions.push_back([this] Duck::print_this(); );
                    void print_this()

                    std::cout << "I'm a duck" << std::endl;

                    ;

                    int main()

                    Duck d;
                    d.print();






                    share|improve this answer















                    We can let the base class keep track of the attributes:



                    #include <iostream>
                    #include <string>
                    #include <vector>

                    using namespace std::string_literals;

                    class Creature

                    public:
                    std::string const attribute"I'm a creature"s;
                    std::vector<std::string> attributesattribute;
                    virtual void print()

                    for (auto& i : attributes)
                    std::cout << i << std::endl;

                    ;

                    class Swimmer : public virtual Creature

                    public:
                    Swimmer() attributes.push_back(attribute);
                    std::string const attribute"I can swim"s;
                    ;

                    class Flier : public virtual Creature

                    public:
                    Flier() attributes.push_back(attribute);
                    std::string const attribute"I can fly"s;
                    ;

                    class Duck : public Flier, public Swimmer

                    public:
                    Duck() attributes.push_back(attribute);
                    std::string const attribute"I'm a duck"s;
                    ;

                    int main()

                    Duck d;
                    d.print();




                    Likewise, if it is not just printing we're after, but rather the function calls, then we could let the base class keep track of the functions:



                    #include <iostream>
                    #include <functional>
                    #include <vector>

                    class Creature

                    public:
                    std::vector<std::function<void()>> print_functions[this] Creature::print_this(); ;
                    virtual void print_this()

                    std::cout << "I'm a creature" << std::endl;

                    void print()

                    for (auto& f : print_functions)
                    f();

                    ;

                    class Swimmer : public virtual Creature

                    public:
                    Swimmer() print_functions.push_back([this] Swimmer::print_this(); );
                    void print_this()

                    std::cout << "I can swim" << std::endl;

                    ;

                    class Flier : public virtual Creature

                    public:
                    Flier() print_functions.push_back([this] Flier::print_this(); );
                    void print_this()

                    std::cout << "I can fly" << std::endl;

                    ;

                    class Duck : public Flier, public Swimmer

                    public:
                    Duck() print_functions.push_back([this] Duck::print_this(); );
                    void print_this()

                    std::cout << "I'm a duck" << std::endl;

                    ;

                    int main()

                    Duck d;
                    d.print();







                    share|improve this answer














                    share|improve this answer



                    share|improve this answer








                    edited Apr 24 at 19:14

























                    answered Apr 24 at 12:25









                    wallywally

                    7,31532346




                    7,31532346







                    • 1





                      That makes every instance allocate an entire std::vector, which is a bit heavy.

                      – Kevin
                      Apr 24 at 19:35






                    • 6





                      @Kevin I'm guessing you won't like vtables either. :)

                      – wally
                      2 days ago











                    • @wally vtables involve storing a pointer to a bit of read-only memory - can often be done in a single move instruction. Vectors involve allocating memory from the heap, which is going to involve grabbing and releasing a mutex, with all the memory barrier and cache-flushing that implies.

                      – Martin Bonner
                      2 days ago






                    • 1





                      @MartinBonner Other threads wouldn't have access to the object until after construction. Why would you need to lock a mutex for the vector? And where did you hear that you need a mutex for heap allocation?

                      – wally
                      2 days ago






                    • 1





                      @MartinBonner If you're referring to the locking that the operating system does then it is unavoidable. I suppose that if you create the vector with the correct size then the extra malloc might be optimized away if you're creating the entire object on the heap anyway. The contention between threads might also be reduced if the OS decided to use separate arenas for the allocations. The OS might also not be using a mutex. In general, defensively designing around this would be impractical. std::vector is not that bad.

                      – wally
                      2 days ago












                    • 1





                      That makes every instance allocate an entire std::vector, which is a bit heavy.

                      – Kevin
                      Apr 24 at 19:35






                    • 6





                      @Kevin I'm guessing you won't like vtables either. :)

                      – wally
                      2 days ago











                    • @wally vtables involve storing a pointer to a bit of read-only memory - can often be done in a single move instruction. Vectors involve allocating memory from the heap, which is going to involve grabbing and releasing a mutex, with all the memory barrier and cache-flushing that implies.

                      – Martin Bonner
                      2 days ago






                    • 1





                      @MartinBonner Other threads wouldn't have access to the object until after construction. Why would you need to lock a mutex for the vector? And where did you hear that you need a mutex for heap allocation?

                      – wally
                      2 days ago






                    • 1





                      @MartinBonner If you're referring to the locking that the operating system does then it is unavoidable. I suppose that if you create the vector with the correct size then the extra malloc might be optimized away if you're creating the entire object on the heap anyway. The contention between threads might also be reduced if the OS decided to use separate arenas for the allocations. The OS might also not be using a mutex. In general, defensively designing around this would be impractical. std::vector is not that bad.

                      – wally
                      2 days ago







                    1




                    1





                    That makes every instance allocate an entire std::vector, which is a bit heavy.

                    – Kevin
                    Apr 24 at 19:35





                    That makes every instance allocate an entire std::vector, which is a bit heavy.

                    – Kevin
                    Apr 24 at 19:35




                    6




                    6





                    @Kevin I'm guessing you won't like vtables either. :)

                    – wally
                    2 days ago





                    @Kevin I'm guessing you won't like vtables either. :)

                    – wally
                    2 days ago













                    @wally vtables involve storing a pointer to a bit of read-only memory - can often be done in a single move instruction. Vectors involve allocating memory from the heap, which is going to involve grabbing and releasing a mutex, with all the memory barrier and cache-flushing that implies.

                    – Martin Bonner
                    2 days ago





                    @wally vtables involve storing a pointer to a bit of read-only memory - can often be done in a single move instruction. Vectors involve allocating memory from the heap, which is going to involve grabbing and releasing a mutex, with all the memory barrier and cache-flushing that implies.

                    – Martin Bonner
                    2 days ago




                    1




                    1





                    @MartinBonner Other threads wouldn't have access to the object until after construction. Why would you need to lock a mutex for the vector? And where did you hear that you need a mutex for heap allocation?

                    – wally
                    2 days ago





                    @MartinBonner Other threads wouldn't have access to the object until after construction. Why would you need to lock a mutex for the vector? And where did you hear that you need a mutex for heap allocation?

                    – wally
                    2 days ago




                    1




                    1





                    @MartinBonner If you're referring to the locking that the operating system does then it is unavoidable. I suppose that if you create the vector with the correct size then the extra malloc might be optimized away if you're creating the entire object on the heap anyway. The contention between threads might also be reduced if the OS decided to use separate arenas for the allocations. The OS might also not be using a mutex. In general, defensively designing around this would be impractical. std::vector is not that bad.

                    – wally
                    2 days ago





                    @MartinBonner If you're referring to the locking that the operating system does then it is unavoidable. I suppose that if you create the vector with the correct size then the extra malloc might be optimized away if you're creating the entire object on the heap anyway. The contention between threads might also be reduced if the OS decided to use separate arenas for the allocations. The OS might also not be using a mutex. In general, defensively designing around this would be impractical. std::vector is not that bad.

                    – wally
                    2 days ago











                    6














                    An easy way is to create a bunch of helper classes that mimick the inheritance structure of your main hierarchy and do all the printing in their constructors.



                     struct CreaturePrinter 
                    CreaturePrinter()
                    std::cout << "I'm a creaturen";

                    ;

                    struct FlierPrinter: virtual CreaturePrinter ...
                    struct SwimmerPrinter: virtual CreaturePrinter ...
                    struct DuckPrinter: FlierPrinter, SwimmerPrinter ...


                    Then each print method in the main hierarchy just creates the corresponding helper class. No manual chaining.



                    For maintainability you can make each printer class nested in its corresponding main class.



                    Naturally in most real world cases you want to pass a reference to the main object as an argument to the constructor of its helper.






                    share|improve this answer





























                      6














                      An easy way is to create a bunch of helper classes that mimick the inheritance structure of your main hierarchy and do all the printing in their constructors.



                       struct CreaturePrinter 
                      CreaturePrinter()
                      std::cout << "I'm a creaturen";

                      ;

                      struct FlierPrinter: virtual CreaturePrinter ...
                      struct SwimmerPrinter: virtual CreaturePrinter ...
                      struct DuckPrinter: FlierPrinter, SwimmerPrinter ...


                      Then each print method in the main hierarchy just creates the corresponding helper class. No manual chaining.



                      For maintainability you can make each printer class nested in its corresponding main class.



                      Naturally in most real world cases you want to pass a reference to the main object as an argument to the constructor of its helper.






                      share|improve this answer



























                        6












                        6








                        6







                        An easy way is to create a bunch of helper classes that mimick the inheritance structure of your main hierarchy and do all the printing in their constructors.



                         struct CreaturePrinter 
                        CreaturePrinter()
                        std::cout << "I'm a creaturen";

                        ;

                        struct FlierPrinter: virtual CreaturePrinter ...
                        struct SwimmerPrinter: virtual CreaturePrinter ...
                        struct DuckPrinter: FlierPrinter, SwimmerPrinter ...


                        Then each print method in the main hierarchy just creates the corresponding helper class. No manual chaining.



                        For maintainability you can make each printer class nested in its corresponding main class.



                        Naturally in most real world cases you want to pass a reference to the main object as an argument to the constructor of its helper.






                        share|improve this answer















                        An easy way is to create a bunch of helper classes that mimick the inheritance structure of your main hierarchy and do all the printing in their constructors.



                         struct CreaturePrinter 
                        CreaturePrinter()
                        std::cout << "I'm a creaturen";

                        ;

                        struct FlierPrinter: virtual CreaturePrinter ...
                        struct SwimmerPrinter: virtual CreaturePrinter ...
                        struct DuckPrinter: FlierPrinter, SwimmerPrinter ...


                        Then each print method in the main hierarchy just creates the corresponding helper class. No manual chaining.



                        For maintainability you can make each printer class nested in its corresponding main class.



                        Naturally in most real world cases you want to pass a reference to the main object as an argument to the constructor of its helper.







                        share|improve this answer














                        share|improve this answer



                        share|improve this answer








                        edited Apr 24 at 14:23

























                        answered Apr 24 at 14:18









                        n.m.n.m.

                        74.5k885173




                        74.5k885173





















                            4














                            Your explicit calls to the print methods form the crux of the issue.



                            One way round this would be to drop the print calls, and replace them with say



                            void queue(std::set<std::string>& data)


                            and you accumulate the print messages into the set. Then it doesn't matter those functions in the hierarchy get called more than once.



                            You then implement the printing of the set in a single method in Creature.



                            If you want to preserve the order of printing, then you'd need to replace the set with another container that respects the order of insertion and rejects duplicates.






                            share|improve this answer




















                            • 2





                              this doesn't solve the problem in general

                              – sudo rm -rf slash
                              Apr 24 at 16:29















                            4














                            Your explicit calls to the print methods form the crux of the issue.



                            One way round this would be to drop the print calls, and replace them with say



                            void queue(std::set<std::string>& data)


                            and you accumulate the print messages into the set. Then it doesn't matter those functions in the hierarchy get called more than once.



                            You then implement the printing of the set in a single method in Creature.



                            If you want to preserve the order of printing, then you'd need to replace the set with another container that respects the order of insertion and rejects duplicates.






                            share|improve this answer




















                            • 2





                              this doesn't solve the problem in general

                              – sudo rm -rf slash
                              Apr 24 at 16:29













                            4












                            4








                            4







                            Your explicit calls to the print methods form the crux of the issue.



                            One way round this would be to drop the print calls, and replace them with say



                            void queue(std::set<std::string>& data)


                            and you accumulate the print messages into the set. Then it doesn't matter those functions in the hierarchy get called more than once.



                            You then implement the printing of the set in a single method in Creature.



                            If you want to preserve the order of printing, then you'd need to replace the set with another container that respects the order of insertion and rejects duplicates.






                            share|improve this answer















                            Your explicit calls to the print methods form the crux of the issue.



                            One way round this would be to drop the print calls, and replace them with say



                            void queue(std::set<std::string>& data)


                            and you accumulate the print messages into the set. Then it doesn't matter those functions in the hierarchy get called more than once.



                            You then implement the printing of the set in a single method in Creature.



                            If you want to preserve the order of printing, then you'd need to replace the set with another container that respects the order of insertion and rejects duplicates.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited 2 days ago









                            Peter Mortensen

                            14k1987114




                            14k1987114










                            answered Apr 24 at 12:26









                            BathshebaBathsheba

                            183k27257385




                            183k27257385







                            • 2





                              this doesn't solve the problem in general

                              – sudo rm -rf slash
                              Apr 24 at 16:29












                            • 2





                              this doesn't solve the problem in general

                              – sudo rm -rf slash
                              Apr 24 at 16:29







                            2




                            2





                            this doesn't solve the problem in general

                            – sudo rm -rf slash
                            Apr 24 at 16:29





                            this doesn't solve the problem in general

                            – sudo rm -rf slash
                            Apr 24 at 16:29











                            4














                            If you want that middle class method, do not call the base class method. The easiest and simplest way is to extract extra methods, and then reimplementing Print is easy.



                            class Creature

                            public:
                            virtual void print()

                            std::cout << "I'm a creature" << std::endl;

                            ;

                            class Swimmer : public virtual Creature

                            public:
                            void print()

                            Creature::print();
                            detailPrint();


                            void detailPrint()

                            std::cout << "I can swim" << std::endl;

                            ;

                            class Flier : public virtual Creature

                            public:
                            void print()

                            Creature::print();
                            detailPrint();


                            void detailPrint()

                            std::cout << "I can fly" << std::endl;

                            ;

                            class Duck : public Flier, public Swimmer

                            public:
                            void print()

                            Creature::Print();
                            Flier::detailPrint();
                            Swimmer::detailPrint();
                            detailPrint();


                            void detailPrint()

                            std::cout << "I'm a duck" << std::endl;

                            ;


                            Without details what is your actual problem is, it hard to come up with a better solution.






                            share|improve this answer





























                              4














                              If you want that middle class method, do not call the base class method. The easiest and simplest way is to extract extra methods, and then reimplementing Print is easy.



                              class Creature

                              public:
                              virtual void print()

                              std::cout << "I'm a creature" << std::endl;

                              ;

                              class Swimmer : public virtual Creature

                              public:
                              void print()

                              Creature::print();
                              detailPrint();


                              void detailPrint()

                              std::cout << "I can swim" << std::endl;

                              ;

                              class Flier : public virtual Creature

                              public:
                              void print()

                              Creature::print();
                              detailPrint();


                              void detailPrint()

                              std::cout << "I can fly" << std::endl;

                              ;

                              class Duck : public Flier, public Swimmer

                              public:
                              void print()

                              Creature::Print();
                              Flier::detailPrint();
                              Swimmer::detailPrint();
                              detailPrint();


                              void detailPrint()

                              std::cout << "I'm a duck" << std::endl;

                              ;


                              Without details what is your actual problem is, it hard to come up with a better solution.






                              share|improve this answer



























                                4












                                4








                                4







                                If you want that middle class method, do not call the base class method. The easiest and simplest way is to extract extra methods, and then reimplementing Print is easy.



                                class Creature

                                public:
                                virtual void print()

                                std::cout << "I'm a creature" << std::endl;

                                ;

                                class Swimmer : public virtual Creature

                                public:
                                void print()

                                Creature::print();
                                detailPrint();


                                void detailPrint()

                                std::cout << "I can swim" << std::endl;

                                ;

                                class Flier : public virtual Creature

                                public:
                                void print()

                                Creature::print();
                                detailPrint();


                                void detailPrint()

                                std::cout << "I can fly" << std::endl;

                                ;

                                class Duck : public Flier, public Swimmer

                                public:
                                void print()

                                Creature::Print();
                                Flier::detailPrint();
                                Swimmer::detailPrint();
                                detailPrint();


                                void detailPrint()

                                std::cout << "I'm a duck" << std::endl;

                                ;


                                Without details what is your actual problem is, it hard to come up with a better solution.






                                share|improve this answer















                                If you want that middle class method, do not call the base class method. The easiest and simplest way is to extract extra methods, and then reimplementing Print is easy.



                                class Creature

                                public:
                                virtual void print()

                                std::cout << "I'm a creature" << std::endl;

                                ;

                                class Swimmer : public virtual Creature

                                public:
                                void print()

                                Creature::print();
                                detailPrint();


                                void detailPrint()

                                std::cout << "I can swim" << std::endl;

                                ;

                                class Flier : public virtual Creature

                                public:
                                void print()

                                Creature::print();
                                detailPrint();


                                void detailPrint()

                                std::cout << "I can fly" << std::endl;

                                ;

                                class Duck : public Flier, public Swimmer

                                public:
                                void print()

                                Creature::Print();
                                Flier::detailPrint();
                                Swimmer::detailPrint();
                                detailPrint();


                                void detailPrint()

                                std::cout << "I'm a duck" << std::endl;

                                ;


                                Without details what is your actual problem is, it hard to come up with a better solution.







                                share|improve this answer














                                share|improve this answer



                                share|improve this answer








                                edited 2 days ago









                                Peter Mortensen

                                14k1987114




                                14k1987114










                                answered Apr 24 at 14:35









                                Marek RMarek R

                                13.9k22778




                                13.9k22778





















                                    2














                                    Use:



                                    template<typename Base, typename Derived>
                                    bool is_dominant_descendant(Derived * x)
                                    return std::abs(
                                    std::distance(
                                    static_cast<char*>(static_cast<void*>(x)),
                                    static_cast<char*>(static_cast<void*>(dynamic_cast<Base*>(x)))
                                    )
                                    ) <= sizeof(Derived);
                                    ;

                                    class Creature

                                    public:
                                    virtual void print()

                                    std::cout << "I'm a creature" << std::endl;

                                    ;

                                    class Walker : public virtual Creature

                                    public:
                                    void print()

                                    if (is_dominant_descendant<Creature>(this))
                                    Creature::print();
                                    std::cout << "I can walk" << std::endl;

                                    ;

                                    class Swimmer : public virtual Creature

                                    public:
                                    void print()

                                    if (is_dominant_descendant<Creature>(this))
                                    Creature::print();
                                    std::cout << "I can swim" << std::endl;

                                    ;

                                    class Flier : public virtual Creature

                                    public:
                                    void print()

                                    if (is_dominant_descendant<Creature>(this))
                                    Creature::print();
                                    std::cout << "I can fly" << std::endl;

                                    ;

                                    class Duck : public Flier, public Swimmer, public Walker

                                    public:
                                    void print()

                                    Walker::print();
                                    Swimmer::print();
                                    Flier::print();
                                    std::cout << "I'm a duck" << std::endl;

                                    ;


                                    And with Visual Studio 2015 the output is:



                                    I'm a creature
                                    I can walk
                                    I can swim
                                    I can fly
                                    I'm a duck


                                    But is_dominant_descendant does not have a portable definition. I wish it were a standard concept.






                                    share|improve this answer





























                                      2














                                      Use:



                                      template<typename Base, typename Derived>
                                      bool is_dominant_descendant(Derived * x)
                                      return std::abs(
                                      std::distance(
                                      static_cast<char*>(static_cast<void*>(x)),
                                      static_cast<char*>(static_cast<void*>(dynamic_cast<Base*>(x)))
                                      )
                                      ) <= sizeof(Derived);
                                      ;

                                      class Creature

                                      public:
                                      virtual void print()

                                      std::cout << "I'm a creature" << std::endl;

                                      ;

                                      class Walker : public virtual Creature

                                      public:
                                      void print()

                                      if (is_dominant_descendant<Creature>(this))
                                      Creature::print();
                                      std::cout << "I can walk" << std::endl;

                                      ;

                                      class Swimmer : public virtual Creature

                                      public:
                                      void print()

                                      if (is_dominant_descendant<Creature>(this))
                                      Creature::print();
                                      std::cout << "I can swim" << std::endl;

                                      ;

                                      class Flier : public virtual Creature

                                      public:
                                      void print()

                                      if (is_dominant_descendant<Creature>(this))
                                      Creature::print();
                                      std::cout << "I can fly" << std::endl;

                                      ;

                                      class Duck : public Flier, public Swimmer, public Walker

                                      public:
                                      void print()

                                      Walker::print();
                                      Swimmer::print();
                                      Flier::print();
                                      std::cout << "I'm a duck" << std::endl;

                                      ;


                                      And with Visual Studio 2015 the output is:



                                      I'm a creature
                                      I can walk
                                      I can swim
                                      I can fly
                                      I'm a duck


                                      But is_dominant_descendant does not have a portable definition. I wish it were a standard concept.






                                      share|improve this answer



























                                        2












                                        2








                                        2







                                        Use:



                                        template<typename Base, typename Derived>
                                        bool is_dominant_descendant(Derived * x)
                                        return std::abs(
                                        std::distance(
                                        static_cast<char*>(static_cast<void*>(x)),
                                        static_cast<char*>(static_cast<void*>(dynamic_cast<Base*>(x)))
                                        )
                                        ) <= sizeof(Derived);
                                        ;

                                        class Creature

                                        public:
                                        virtual void print()

                                        std::cout << "I'm a creature" << std::endl;

                                        ;

                                        class Walker : public virtual Creature

                                        public:
                                        void print()

                                        if (is_dominant_descendant<Creature>(this))
                                        Creature::print();
                                        std::cout << "I can walk" << std::endl;

                                        ;

                                        class Swimmer : public virtual Creature

                                        public:
                                        void print()

                                        if (is_dominant_descendant<Creature>(this))
                                        Creature::print();
                                        std::cout << "I can swim" << std::endl;

                                        ;

                                        class Flier : public virtual Creature

                                        public:
                                        void print()

                                        if (is_dominant_descendant<Creature>(this))
                                        Creature::print();
                                        std::cout << "I can fly" << std::endl;

                                        ;

                                        class Duck : public Flier, public Swimmer, public Walker

                                        public:
                                        void print()

                                        Walker::print();
                                        Swimmer::print();
                                        Flier::print();
                                        std::cout << "I'm a duck" << std::endl;

                                        ;


                                        And with Visual Studio 2015 the output is:



                                        I'm a creature
                                        I can walk
                                        I can swim
                                        I can fly
                                        I'm a duck


                                        But is_dominant_descendant does not have a portable definition. I wish it were a standard concept.






                                        share|improve this answer















                                        Use:



                                        template<typename Base, typename Derived>
                                        bool is_dominant_descendant(Derived * x)
                                        return std::abs(
                                        std::distance(
                                        static_cast<char*>(static_cast<void*>(x)),
                                        static_cast<char*>(static_cast<void*>(dynamic_cast<Base*>(x)))
                                        )
                                        ) <= sizeof(Derived);
                                        ;

                                        class Creature

                                        public:
                                        virtual void print()

                                        std::cout << "I'm a creature" << std::endl;

                                        ;

                                        class Walker : public virtual Creature

                                        public:
                                        void print()

                                        if (is_dominant_descendant<Creature>(this))
                                        Creature::print();
                                        std::cout << "I can walk" << std::endl;

                                        ;

                                        class Swimmer : public virtual Creature

                                        public:
                                        void print()

                                        if (is_dominant_descendant<Creature>(this))
                                        Creature::print();
                                        std::cout << "I can swim" << std::endl;

                                        ;

                                        class Flier : public virtual Creature

                                        public:
                                        void print()

                                        if (is_dominant_descendant<Creature>(this))
                                        Creature::print();
                                        std::cout << "I can fly" << std::endl;

                                        ;

                                        class Duck : public Flier, public Swimmer, public Walker

                                        public:
                                        void print()

                                        Walker::print();
                                        Swimmer::print();
                                        Flier::print();
                                        std::cout << "I'm a duck" << std::endl;

                                        ;


                                        And with Visual Studio 2015 the output is:



                                        I'm a creature
                                        I can walk
                                        I can swim
                                        I can fly
                                        I'm a duck


                                        But is_dominant_descendant does not have a portable definition. I wish it were a standard concept.







                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited 2 days ago









                                        Peter Mortensen

                                        14k1987114




                                        14k1987114










                                        answered Apr 24 at 18:26









                                        Red.WaveRed.Wave

                                        94337




                                        94337





















                                            1














                                            You are asking for something like inheritance on a function level that automatically calls the inherited function and just adds more code. Also you want it to be done in a virtual way just like class inheritance. Pseudo syntax:



                                            class Swimmer : public virtual Creature

                                            public:
                                            // Virtually inherit from Creature::print and extend it by another line of code
                                            void print() : virtual Creature::print()

                                            std::cout << "I can swim" << std::endl;

                                            ;

                                            class Flier : public virtual Creature

                                            public:
                                            // Virtually inherit from Creature::print and extend it by another line of code
                                            void print() : virtual Creature::print()

                                            std::cout << "I can fly" << std::endl;

                                            ;

                                            class Duck : public Flier, public Swimmer

                                            public:
                                            // Inherit from both prints. As they were created using "virtual function inheritance",
                                            // this will "mix" them just like in virtual class inheritance
                                            void print() : Flier::print(), Swimmer::print()

                                            std::cout << "I'm a duck" << std::endl;

                                            ;


                                            So the answer to your question




                                            Is there some built-in way to do this?




                                            is no. Something like this does not exist in C++. Also, I'm not aware of any other language that has something like this. But it is an interesting idea...






                                            share|improve this answer





























                                              1














                                              You are asking for something like inheritance on a function level that automatically calls the inherited function and just adds more code. Also you want it to be done in a virtual way just like class inheritance. Pseudo syntax:



                                              class Swimmer : public virtual Creature

                                              public:
                                              // Virtually inherit from Creature::print and extend it by another line of code
                                              void print() : virtual Creature::print()

                                              std::cout << "I can swim" << std::endl;

                                              ;

                                              class Flier : public virtual Creature

                                              public:
                                              // Virtually inherit from Creature::print and extend it by another line of code
                                              void print() : virtual Creature::print()

                                              std::cout << "I can fly" << std::endl;

                                              ;

                                              class Duck : public Flier, public Swimmer

                                              public:
                                              // Inherit from both prints. As they were created using "virtual function inheritance",
                                              // this will "mix" them just like in virtual class inheritance
                                              void print() : Flier::print(), Swimmer::print()

                                              std::cout << "I'm a duck" << std::endl;

                                              ;


                                              So the answer to your question




                                              Is there some built-in way to do this?




                                              is no. Something like this does not exist in C++. Also, I'm not aware of any other language that has something like this. But it is an interesting idea...






                                              share|improve this answer



























                                                1












                                                1








                                                1







                                                You are asking for something like inheritance on a function level that automatically calls the inherited function and just adds more code. Also you want it to be done in a virtual way just like class inheritance. Pseudo syntax:



                                                class Swimmer : public virtual Creature

                                                public:
                                                // Virtually inherit from Creature::print and extend it by another line of code
                                                void print() : virtual Creature::print()

                                                std::cout << "I can swim" << std::endl;

                                                ;

                                                class Flier : public virtual Creature

                                                public:
                                                // Virtually inherit from Creature::print and extend it by another line of code
                                                void print() : virtual Creature::print()

                                                std::cout << "I can fly" << std::endl;

                                                ;

                                                class Duck : public Flier, public Swimmer

                                                public:
                                                // Inherit from both prints. As they were created using "virtual function inheritance",
                                                // this will "mix" them just like in virtual class inheritance
                                                void print() : Flier::print(), Swimmer::print()

                                                std::cout << "I'm a duck" << std::endl;

                                                ;


                                                So the answer to your question




                                                Is there some built-in way to do this?




                                                is no. Something like this does not exist in C++. Also, I'm not aware of any other language that has something like this. But it is an interesting idea...






                                                share|improve this answer















                                                You are asking for something like inheritance on a function level that automatically calls the inherited function and just adds more code. Also you want it to be done in a virtual way just like class inheritance. Pseudo syntax:



                                                class Swimmer : public virtual Creature

                                                public:
                                                // Virtually inherit from Creature::print and extend it by another line of code
                                                void print() : virtual Creature::print()

                                                std::cout << "I can swim" << std::endl;

                                                ;

                                                class Flier : public virtual Creature

                                                public:
                                                // Virtually inherit from Creature::print and extend it by another line of code
                                                void print() : virtual Creature::print()

                                                std::cout << "I can fly" << std::endl;

                                                ;

                                                class Duck : public Flier, public Swimmer

                                                public:
                                                // Inherit from both prints. As they were created using "virtual function inheritance",
                                                // this will "mix" them just like in virtual class inheritance
                                                void print() : Flier::print(), Swimmer::print()

                                                std::cout << "I'm a duck" << std::endl;

                                                ;


                                                So the answer to your question




                                                Is there some built-in way to do this?




                                                is no. Something like this does not exist in C++. Also, I'm not aware of any other language that has something like this. But it is an interesting idea...







                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited 2 days ago









                                                Peter Mortensen

                                                14k1987114




                                                14k1987114










                                                answered 2 days ago









                                                sebrockmsebrockm

                                                1,8751320




                                                1,8751320



























                                                    draft saved

                                                    draft discarded
















































                                                    Thanks for contributing an answer to Stack Overflow!


                                                    • Please be sure to answer the question. Provide details and share your research!

                                                    But avoid


                                                    • Asking for help, clarification, or responding to other answers.

                                                    • Making statements based on opinion; back them up with references or personal experience.

                                                    To learn more, see our tips on writing great answers.




                                                    draft saved


                                                    draft discarded














                                                    StackExchange.ready(
                                                    function ()
                                                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55829798%2fc-diamond-problem-how-to-call-base-method-only-once%23new-answer', 'question_page');

                                                    );

                                                    Post as a guest















                                                    Required, but never shown





















































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown

































                                                    Required, but never shown














                                                    Required, but never shown












                                                    Required, but never shown







                                                    Required, but never shown







                                                    Popular posts from this blog

                                                    How does Billy Russo acquire his 'Jigsaw' mask? Unicorn Meta Zoo #1: Why another podcast? Announcing the arrival of Valued Associate #679: Cesar Manara Favourite questions and answers from the 1st quarter of 2019Why does Bane wear the mask?Why does Kylo Ren wear a mask?Why did Captain America remove his mask while fighting Batroc the Leaper?How did the OA acquire her wisdom?Is Billy Breckenridge gay?How does Adrian Toomes hide his earnings from the IRS?What is the state of affairs on Nootka Sound by the end of season 1?How did Tia Dalma acquire Captain Barbossa's body?How is one “Deemed Worthy”, to acquire the Greatsword “Dawn”?How did Karen acquire the handgun?

                                                    Личност Атрибути на личността | Литература и източници | НавигацияРаждането на личносттаредактиратередактирате

                                                    A sequel to Domino's tragic life Why Christmas is for Friends Cold comfort at Charles' padSad farewell for Lady JanePS Most watched News videos