Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8499557
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 11, 20262026-06-11T00:42:01+00:00 2026-06-11T00:42:01+00:00

Consider classic virtual inheritance diamond hierarchy. I wonder to know what is the right

  • 0

Consider classic virtual inheritance diamond hierarchy. I wonder to know what is the right implementation of copy and swap idiom in such hierarchy.

The example is a little artificial – and it is not very smart – as it would play good with default copy semantic for A,B,D classes. But just to illustrate the problem – please forget about the example weaknesses and provide the solution.

So I have class D derived from 2 base classes (B<1>,B<2>) – each of B classes inherits virtually from A class. Each class has non trivial copy semantics with using of copy and swap idiom. The most derived D class has problem with using this idiom. When it calls B<1> and B<2> swap methods – it swaps virtual base class members twice – so A subobject remains unchanged!!!

A:

class A {
public:
  A(const char* s) : s(s) {}
  A(const A& o) : s(o.s) {}
  A& operator = (A o)
  {
     swap(o);
     return *this;
  }
  virtual ~A() {}
  void swap(A& o)
  {
     s.swap(o.s);
  }
  friend std::ostream& operator << (std::ostream& os, const A& a) { return os << a.s; }

private:
  S s;
};

B

template <int N>
class B : public virtual A {
public:
  B(const char* sA, const char* s) : A(sA), s(s) {}
  B(const B& o) : A(o), s(o.s) {}
  B& operator = (B o)
  {
     swap(o);
     return *this;
  }
  virtual ~B() {}
  void swap(B& o)
  {
     A::swap(o);
     s.swap(o.s);
  }
  friend std::ostream& operator << (std::ostream& os, const B& b) 
  { return os << (const A&)b << ',' << b.s; }

private:
  S s;
};

D:

class D : public B<1>, public B<2> {
public:
  D(const char* sA, const char* sB1, const char* sB2, const char* s) 
   : A(sA), B<1>(sA, sB1), B<2>(sA, sB2), s(s) 
  {}
  D(const D& o) : A(o), B<1>(o), B<2>(o), s(o.s) {}
  D& operator = (D o)
  {
     swap(o);
     return *this;
  }
  virtual ~D() {}
  void swap(D& o)
  {
     B<1>::swap(o); // calls A::swap(o); A::s changed to o.s
     B<2>::swap(o); // calls A::swap(o); A::s returned to original value...
     s.swap(o.s);
  }
  friend std::ostream& operator << (std::ostream& os, const D& d) 
  { 
     // prints A::s twice...
     return os 
    << (const B<1>&)d << ',' 
    << (const B<2>&)d << ',' 
        << d.s;
  }
private:
  S s;
};

S is just a class storing string.

When doing copy you will see A::s remains unchanged:

int main() {
   D x("ax", "b1x", "b2x", "x");
   D y("ay", "b1y", "b2y", "y");
   std::cout << x << "\n" << y << "\n";
   x = y;
   std::cout << x << "\n" << y << "\n";
}

And the result is:

ax,b1x,ax,b2x,x
ay,b1y,ay,b2y,y
ax,b1y,ax,b2y,y
ay,b1y,ay,b2y,y

Probably adding B<N>::swapOnlyMewould resolve the problem:

void B<N>::swapOnlyMe(B<N>& b) { std::swap(s, b.s); }
void D::swap(D& d) { A::swap(d); B<1>::swapOnlyMe((B<1>&)d); B<2>::swapOnlyMe((B<2>&)d); ... }

But what when B inherits privately from A?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-11T00:42:03+00:00Added an answer on June 11, 2026 at 12:42 am

    Here’s a philosophical rant:

    1. I don’t think virtual inheritance can or should be private. The entire point of a virtual base is that the most derived class owns the virtual base, and not the intermediate classes. Thus no intermediate class should be permitted to “hog” the virtual base.

    2. Let me repeat the point: The most derived class owns the virtual base. This is evident in constructor initializers:

      D::D() : A(), B(), C() { }
      //       ^^^^
      //       D calls the virtual base constructor!
      

      In the same sense, all other operations in D should be immediately responsible for A. Thus we are naturally led to writing the derived swap function like this:

      void D::swap(D & rhs)
      {
          A::swap(rhs);   // D calls this directly!
          B::swap(rhs);
          C::swap(rhs);
      
          // swap members
      }
      
    3. Putting all this together, we’re left with only one possible conclusion: You have to write the swap functions of the intermediate classes without swapping the base:

      void B::swap(B & rhs)
      {
          // swap members only!
      }
      
      void C::swap(C & rhs)
      {
          // swap members only!
      }
      

    Now you ask, “what if someone else wants to derive from D? Now we see the reason for Scott Meyer’s advice to always make non-leaf classes abstract: Following that advice, you only implement the final swap function which calls the virtual base swap in the concrete, leaf classes.


    Update: Here’s something only tangentially related: Virtual swapping. We continue to assume that all non-leaf classes are abstract. First off, we put the following “virtual swap function” into every base class (virtual or not):

    struct A
    {
        virtual void vswap(A &) = 0;
        // ...
    };
    

    Usage of this function is of course reserved only to identical types. This is safeguarded by an implicit exception:

    struct D : /* inherit */
    {
        virtual void vswap(A & rhs) { swap(dynamic_cast<D &>(rhs)); }
    
        // rest as before
    };
    

    The overall utility of this is limited, but it does allow us swap to objects polymorphically if we happen to know that they’re the same:

    std::unique_ptr<A> p1 = make_unique<D>(), p2 = make_unique<D>();
    p1->vswap(*p2);
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Consider this classic example used to explain what not to do with forward declarations:
Consider the following scenario: Page written in classic ASP or PHP, which is rendering
Consider this example: When the user clicks a button, ClassA fires OnUserInteraction event rapidly
I am a classic ASP developer. I know, I should learn .NET, but only
Consider a virtual memory system with 32-bit virtual addresses and 1KB pages. Each page
Consider a classic LDAP usage for authentication and consequent calls to check if the
We've got a large classic asp application and we consider migrating to either asp.net
Consider the following simple example: private Action _action; public Form1() { InitializeComponent(); } private
Consider having the following header file (c++): myclass.hpp #ifndef MYCLASSHPP_ #define MYCLASSHPP_ namespace A
Consider the following C#: // C# .net switch(x) { case 1: for(int i =

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.