EN VI

C++ - Redefining swap function in inherited classes?

2024-03-17 20:00:06
How to C++ - Redefining swap function in inherited classes?

Hey I just implemented the big three plus an copy and swap idiom assignment operator in my class. However, I have some other classes inheriting of this super class, and now I asked myself if I should redifine this swap method in the sub classes.

Should I make the swap method to privat in every single class? Should I make the swap method virtual? What do you guys suggest?

Tyvm!

Header files:

Superclass:

#ifndef USER_H
#define USER_H

#include <string>

class user
{

public:
  explicit user();
  //user(std::string&, const int);
  user(std::string&, const int, std::string&, std::string&);
  ~user(){};

  // Big three/four...
  user(const user&);   // Copy constructor
  user(user&&);        // move contructor
  user& operator=(user); // Copy/Move assignment
  // + destructor
  
  
  // Swap function for move assignment
  friend void swap(user& first, user& second) 
  {
    std::swap(first.name_m, second.name_m);
    std::swap(first.id_m, second.id_m);
    std::swap(first.class_m, second.class_m);
    std::swap(first.rights_m, second.rights_m);
  }
  
  virtual void printDescription() const;

  void setName(const std::string&);
  void setId(const int);
  void setClass(const std::string&);
  void setRights(const std::string&);

  const std::string& getName() const;
  const int getId() const;
  const std::string& getClass() const;
  const std::string& getRights() const;
  
protected:
  std::string name_m;
  int id_m;
  std::string class_m;
  std::string rights_m;
};

#endif

Subclass:

#ifndef USER_ADMIN_H
#define USER_ADMIN_H

#include "user.hpp"

#include <string>

struct properties_txt
{
  std::string class_admin = std::string("admin");
  std::string rights_admin = std::string("admin rights");
};

class user_admin : public user
{
public:

  explicit user_admin();
  user_admin(std::string&, const int);
  user_admin(std::string&, const int, std::string&, std::string&);
  ~user_admin();

  user_admin(const user_admin&);
  user_admin(user_admin&&);
  user_admin& operator=(user_admin);

  // Swap function for move assignment
  friend void swap(user& first, user& second)  // Doesnt work obviously
  {
    std::swap(first.name_m, second.name_m);
    std::swap(first.id_m, second.id_m);
    std::swap(first.class_m, second.class_m);
    std::swap(first.rights_m, second.rights_m);
  }
  
  void printDescription() const override;
  
private:
  
};


#endif

Just asking whats best

Solution:

Since the derived class doesn't add any fields, it shouldn't provide a custom swap at all. The one from the base class will be used automatically.

If it did have extra members, the swap should've been implemented as:

using std::swap;
swap(static_cast<user &>(first), static_cast<user &>(second));
swap(first.extra, second.extra); // Only swap the fields added in the derived class.

Some other things:

  • Move constructor, copy&swap operator=, and swap() all should be noexcept.
  • Unless you're doing this for practice, you should follow the rule of 0 and get rid of all those custom copy/move constructors, assignment operators, and swap(). The implicitly generated ones will work just fine.
  • Setters should accept parameters by value, then std::move them.
  • Might be a good idea to get into the habit of writing using std::swap; swap(...); instead of calling std::swap directly, to be able to utilize custom swap without having to think whether you need to omit std:: or not for each individual type.
Answer

Login


Forgot Your Password?

Create Account


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

Reset Password

Back to login