简体   繁体   中英

In has-a relation is it a good design, to access and alter the private members of contained class directly from the Parent class method

Consider this example:

class Child
{
   private:
   string m_Name;

   public:
   string* GetNameAccess()
   {
      return &m_Name;
   }
};

class Parent
{
   private:
   Child m_Child;

   public:
   void DoSomething()
   {
      string *pChildName = m_Child.GetNameAccess();  // Is this the right thing to do?
      *pChildName = "NewName";
   }
};

In has-relation we know that Parent object owns the child object (ie controls the lifetime of child). So is Parent allowed to directly access the private members of child and alter them ?

Although having a public function that returns a pointer to a private data member is legal in C++, it breaks the whole point of encapsulation. As mentioned in the comments, if you want to provide such 'direct' access to the data member, then just make it public.

But there are many good reasons why a data member should be private – such as offering some control(s) over what values are allowed or disallowed for that member. In such circumstances, you should provide genuine 'getter' and 'setter' functions to allow controlled access to that private member from outside the class. The 'getter' should not allow modification of the data (so returning a const& reference is generally appropriate) and the 'setter' should perform the required checks on the value it is given, before making a modification to the data.

Here is a very brief outline of how such a 'getter' and 'setter' may look for your example:

#include <string>

class Child {
private:
    std::string m_Name;
public:
    const std::string& GetName() { // The "const" prevents modification with the getter
        return m_Name;
    }
    void SetName(const std::string& name) {
        // A real setter allows error checking ...
        if (name != "Attila the Hun") m_Name = name;
    }
};

class Parent {
private:
    Child m_Child;
public:
    void DoSomething() {
        std::string temp = m_Child.GetName();
        if (temp.empty()) temp = "New Name";
        else temp += " (Modified)";
        m_Child.SetName(temp);
    }
};

This short snippet demonstrates how you could prevent a parent naming their child, "Attila the Hun," which is perhaps a reasonable precaution for a setter function to implement.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM