【问题标题】:Accessing member in nested composition in C++在 C++ 中访问嵌套组合中的成员
【发布时间】:2020-10-13 15:40:50
【问题描述】:

如果我有一个类包含另一个类(通过组合),而另一个类又包含另一个类。例如:包含 PersonalDetails 类的 Teacher 类,其中包含 ContactInformation 类。

ContactInformation 类:

class ContactInformation
{
private:
    std::string m_email{};
    std::string m_phoneNumber{};

public:
    ContactInformation(const std::string &email, const std::string &phone)
        : m_email{ email }, m_phoneNumber{ phone }
    {
    }

    // Solution 1
    const std::string& getEmail() const { return m_email; }
    const std::string& getPhoneNumber() const { return m_phoneNumber; }

    // Solution 2
    const ContactInformation& getContactInfo() const { return *this; }

    // Solution 3
    friend class Teacher;
};

PersonalDetails 类:

class PersonalDetails
{
private:
    ContactInformation m_contact;
    std::string m_name;

public:
    PersonalDetails(const ContactInformation &info, const std::string &name)
        : m_contact{ info }, m_name{ name }
    {
    }


    // Solution 1
    const std::string& getEmail() const { return m_contact.getEmail(); }
    const std::string& getPhoneNumber() const { return m_contact.getPhoneNumber(); }
    const std::string& getName() const { return m_name; }


    // Solution 2
    const ContactInformation& getContactInfo() const { return m_contact.getContactInfo(); }
    const PersonalDetails& getPersonalDetails() const { return *this; }

    // Solution 3
    friend class Teacher;
};

教师班:

class Teacher
{
private:
    PersonalDetails m_details;
    double m_salary{};

public:
    Teacher(const PersonalDetails &details, double salary)
        : m_details{ details }, m_salary{ salary }
    {
    }

    // Solution 1
    const std::string& getEmail() const { return m_details.getEmail(); }
    const std::string& getPhoneNumber() const { return m_details.getPhoneNumber(); }
    const std::string& getName() const { return m_details.getName(); }
    double getSalary() const { return m_salary; }

    void printEmail1() const 
    {
        std::cout << getEmail() << '\n';
    }


    // Solution 2
    const ContactInformation& getContactInfo() const { return m_details.getContactInfo(); }
    const PersonalDetails& getPersonalDetails() const { return m_details.getPersonalDetails(); }

    void printEmail2() const 
    {
        std::cout << getContactInfo().getEmail() << '\n';
    }


    // Solution 3
    const std::string& getTeacherEmail(const ContactInformation &c) const
    {
        return c.getEmail();
    } 

    void printEmail3() const
    {
        std::cout << getTeacherEmail(getContactInformation());
    }

};

Teacher 类访问 ContactInformation(最“嵌套”类)中的成员(m_email 和 m_phoneNumber)的“正确方式”是什么? 我想出的解决方案都没有那么好。

解决方案 1;是为所有类中的成员变量提供getter方法。但这似乎是个坏主意,因为 Teacher 类最终会有很多 getter 方法。特别是如果我将来要添加更多课程。

解决方案 2;是返回实例本身。我不知道这是否更好,或者它是否违反了任何最佳实践。但是你可以使用 Teacher 类中的实例来调用 getEmail() 。

解决方案 3;正在使用朋友课程(没有很多使用它们的经验)。但由于您仍然必须传递一个 ContactInformation 实例才能获取 m_email。它似乎与解决方案 2 没有太大区别。

有什么方法可以让 Teacher 类成为 ContactInformation 类的朋友(或其他东西),这样我就可以做这样的事情:

teacher.getEmail(); 

除了 ContactInformation 中的 getter 之外,不需要任何 getter?

【问题讨论】:

  • 我尽量避免使用 getter/setter 方法,而是尝试遵循“告诉,不要问”原则 (TDA) 或也称为“好莱坞原则”(不要打电话给我们,我们会叫你)——换句话说,不要让 Teacher 对象被动地保存数据,而是让它有行为。但如果 TDA 在这种情况下不起作用,我会让 Teacher getter 调用它的成员的 PersonalDetails getter,并让 PersonalDetails getter 调用其成员的 ContactInformation getter。
  • 使用 getter 和 setter 与正确封装相反。与其需要传递其内部数据的数据结构,不如将它们视为交互对象。我不记得在哪次谈话中听到过这样一个伟大的比喻:当你去酒吧时,服务员不会打开你的钱包,清点你所有的钱,减去一瓶啤酒的价格,然后把差额放回你的钱包(但这就是这个 setter/getter 狂热导致 customer.setMoney( customer.getMoney() - priceForOneBeer); 的地方)
  • @idclev463035818 我可能应该尝试找到一些关于 TDA 的好资源,似乎它真的可以帮助我更好地构建我的程序。但是如果我要遵循“告诉,不要问”的原则,我将如何重组我的程序?在 Teacher 而不是 ContactInfo 类中使用 printEmail() 可能是一个不好的例子。但是,如果我有一个接受 ContactInformation 类型的对象的外部函数,那该怎么办呢?我是否应该尝试将该逻辑放入 ContactInfo 类中?

标签: c++ composition member-variables


【解决方案1】:

friends 课程的问题在于,您将失去使用ContactInformationTeacher 不同的课程的可能性(将来),而不会从中获得太多收益。

如果PeronalDetailsTeacher 的成员并且ContactInformationPeronalDetails 的成员。你可以简单地teacher.personalDetails.contactInformation.m_email 这很长并且要求所有这些成员都是public

中间点可以是个性化的吸气剂:

public:
Teacher::getEmail(){
    return personalDetails.contactInformation.m_email;
}

【讨论】:

    猜你喜欢
    • 2020-02-16
    • 1970-01-01
    • 2010-11-09
    • 2013-10-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多