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

How do I weigh a kitchen island to determine what size castors to get?

A demigod among men

Does wall of stone need support or not?

Variable fixing based on a good feasible solution

What is the ring of invariants under the action of an arbitrary subgroup of the symmetric group?

Did Feynman cite a fallacy about only circles having the same width in all directions as a reason for the Challenger disaster?

Slow coworker receiving compliments while I receive complaints

How can demon technology be prevented from surpassing humans?

What does "drop" mean in this context?

Would removing the "total cover" part of a Paladin's Divine Sense unbalance the feature?

What is the word for things that work even when they aren't working (e.g. escalators)?

Is there a practical way of making democratic-like system skewed towards competence?

How is a smaller batch size in Kanban increasing performance?

Is data science mathematically interesting?

Novel set in the future, children cannot change the class they are born into, one class is made uneducated by associating books with pain

C4_4 Reflection!

Are there any rules around when something can be described as "based on a true story"?

UK PM is taking his proposal to EU but has not proposed to his own parliament - can he legally bypass the UK parliament?

Big Bracket for equations

Giving a character trauma but not "diagnosing" her?

First aid scissors confiscated by Dubai airport security

Why is it so hard to land on the Moon?

Can the bass be used instead of drums?

Is It Possible to Make a Computer Virus That Acts as an Anti-virus?



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
margin-bottom:0;









37

















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























  • 17





    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!

    – Wilfred Smith
    Apr 25 at 11:04

















37

















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























  • 17





    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!

    – Wilfred Smith
    Apr 25 at 11:04













37












37








37


8






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



share|improve this question








edited Apr 25 at 11:30









Peter Mortensen

14.5k19 gold badges89 silver badges118 bronze badges




14.5k19 gold badges89 silver badges118 bronze badges










asked Apr 24 at 12:14









O. AroestiO. Aroesti

4135 silver badges16 bronze badges




4135 silver badges16 bronze badges










  • 17





    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!

    – Wilfred Smith
    Apr 25 at 11:04












  • 17





    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!

    – Wilfred Smith
    Apr 25 at 11:04







17




17





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!

– Wilfred Smith
Apr 25 at 11:04





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!

– Wilfred Smith
Apr 25 at 11:04












7 Answers
7






active

oldest

votes


















2


















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



































    50


















    Most likely this is a 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



































      22


















      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
        Apr 24 at 22:57











      • @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
        Apr 25 at 12:18






      • 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
        Apr 25 at 13:23






      • 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
        Apr 25 at 14:36


















      8


















      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



































        5


















        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


















        5


















        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


















          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





























            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/4.0/"u003ecc by-sa 4.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









            2


















            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
































              2


















              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






























                2














                2










                2









                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



                share|improve this answer








                edited Apr 25 at 11:43









                Peter Mortensen

                14.5k19 gold badges89 silver badges118 bronze badges




                14.5k19 gold badges89 silver badges118 bronze badges










                answered Apr 25 at 11:23









                sebrockmsebrockm

                2,6981 gold badge4 silver badges23 bronze badges




                2,6981 gold badge4 silver badges23 bronze badges


























                    50


















                    Most likely this is a 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
































                      50


















                      Most likely this is a 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






























                        50














                        50










                        50









                        Most likely this is a 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 a 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



                        share|improve this answer








                        edited May 1 at 0:25

























                        answered Apr 24 at 12:29









                        SwordfishSwordfish

                        1




                        1
























                            22


















                            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
                              Apr 24 at 22:57











                            • @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
                              Apr 25 at 12:18






                            • 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
                              Apr 25 at 13:23






                            • 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
                              Apr 25 at 14:36















                            22


















                            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
                              Apr 24 at 22:57











                            • @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
                              Apr 25 at 12:18






                            • 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
                              Apr 25 at 13:23






                            • 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
                              Apr 25 at 14:36













                            22














                            22










                            22









                            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



                            share|improve this answer








                            edited Apr 24 at 19:14

























                            answered Apr 24 at 12:25









                            wallywally

                            7,8483 gold badges25 silver badges47 bronze badges




                            7,8483 gold badges25 silver badges47 bronze badges










                            • 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
                              Apr 24 at 22:57











                            • @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
                              Apr 25 at 12:18






                            • 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
                              Apr 25 at 13:23






                            • 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
                              Apr 25 at 14:36












                            • 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
                              Apr 24 at 22:57











                            • @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
                              Apr 25 at 12:18






                            • 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
                              Apr 25 at 13:23






                            • 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
                              Apr 25 at 14:36







                            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
                            Apr 24 at 22:57





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

                            – wally
                            Apr 24 at 22:57













                            @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
                            Apr 25 at 12:18





                            @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
                            Apr 25 at 12:18




                            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
                            Apr 25 at 13:23





                            @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
                            Apr 25 at 13:23




                            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
                            Apr 25 at 14:36





                            @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
                            Apr 25 at 14:36











                            8


















                            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
































                              8


















                              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






























                                8














                                8










                                8









                                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



                                share|improve this answer








                                edited Apr 24 at 14:23

























                                answered Apr 24 at 14:18









                                n.m.n.m.

                                79.8k11 gold badges95 silver badges182 bronze badges




                                79.8k11 gold badges95 silver badges182 bronze badges
























                                    5


















                                    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















                                    5


















                                    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













                                    5














                                    5










                                    5









                                    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



                                    share|improve this answer








                                    edited Apr 25 at 11:34









                                    Peter Mortensen

                                    14.5k19 gold badges89 silver badges118 bronze badges




                                    14.5k19 gold badges89 silver badges118 bronze badges










                                    answered Apr 24 at 12:26









                                    BathshebaBathsheba

                                    195k28 gold badges292 silver badges413 bronze badges




                                    195k28 gold badges292 silver badges413 bronze badges










                                    • 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











                                    5


















                                    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
































                                      5


















                                      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






























                                        5














                                        5










                                        5









                                        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



                                        share|improve this answer








                                        edited Apr 25 at 11:37









                                        Peter Mortensen

                                        14.5k19 gold badges89 silver badges118 bronze badges




                                        14.5k19 gold badges89 silver badges118 bronze badges










                                        answered Apr 24 at 14:35









                                        Marek RMarek R

                                        15.7k3 gold badges30 silver badges81 bronze badges




                                        15.7k3 gold badges30 silver badges81 bronze badges
























                                            4


















                                            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
































                                              4


















                                              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






























                                                4














                                                4










                                                4









                                                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



                                                share|improve this answer








                                                edited Apr 25 at 11:38









                                                Peter Mortensen

                                                14.5k19 gold badges89 silver badges118 bronze badges




                                                14.5k19 gold badges89 silver badges118 bronze badges










                                                answered Apr 24 at 18:26









                                                Red.WaveRed.Wave

                                                1,0684 silver badges7 bronze badges




                                                1,0684 silver badges7 bronze badges































                                                    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

                                                    Distance measures on a map of a game The 2019 Stack Overflow Developer Survey Results Are Inmin distance in a graphShortest distance path on contour plotHow to plot a tilted map?Finding points outside of a diskDelaunay link distanceAnnulus from GeoDisks: drawing a ring on a mapNegative Correlation DistanceFind distance along a path (GPS coordinates)Finding position at given distance in a GeoPathMathematics behind distance estimation using camera

                                                    How to get a smooth, uniform ParametricPlot of a 2D Region?How to plot a complicated Region?How to exclude a region from ParametricPlotHow discretize a region placing vertices on a specific non-uniform gridHow to transform a Plot or a ParametricPlot into a RegionHow can I get a smooth plot of a bounded region?Smooth ParametricPlot3D with RegionFunction?Smooth border of a region ParametricPlotSmooth region boundarySmooth region plot from list of pointsGet minimum y of a certain x in a region

                                                    Genealogie vun de Merowenger Vum Merowech bis zum Chilperich I. | Navigatiounsmenü