是C++;同龄人之间的友谊健康吗? 尽管阶级友谊是C++最后的手段之一,这种模式有意义吗?< /P> class Peer { public: friend class Peer; void GetSecret(const Peer& other) { const std::string& secret = other.GiveSecret(); std::cout << secret << std::endl; } private: const std::string& GiveSecret() const { return "secrety stuff"; } }; int main(int argc, char* argv[]) { Peer peerA; Peer peerB; peerA.GetSecret(peerB); return 0; } 类对等 { 公众: 朋辈; void GetSecret(常量对等和其他) { const std::string&secret=other.GiveSecret(); std::cout

是C++;同龄人之间的友谊健康吗? 尽管阶级友谊是C++最后的手段之一,这种模式有意义吗?< /P> class Peer { public: friend class Peer; void GetSecret(const Peer& other) { const std::string& secret = other.GiveSecret(); std::cout << secret << std::endl; } private: const std::string& GiveSecret() const { return "secrety stuff"; } }; int main(int argc, char* argv[]) { Peer peerA; Peer peerB; peerA.GetSecret(peerB); return 0; } 类对等 { 公众: 朋辈; void GetSecret(常量对等和其他) { const std::string&secret=other.GiveSecret(); std::cout,c++,class-design,friend,C++,Class Design,Friend,不健康,它破坏了封装最佳实践 这种模式有意义吗 不多,你能详细说明一下吗 您通常在不同的类之间创建友谊。这在语法上是有效的。为什么Peer是Peer的朋友 私有函数只能由成员函数使用。从客户端代码调用它们是错误的 至于友谊是否会破坏封装的问题,请看下面的例子 抱歉,Robert,误读了名称。在这种情况下不需要friend。类的对象可以访问相同类型的任何其他对象的私有成员。如果没有friend声明,它应该可以正常工作 不健康,它破坏了封装最佳实践 嗯,是和否 只有在不使用方法访问所需数据时,它

不健康,它破坏了封装最佳实践

这种模式有意义吗

不多,你能详细说明一下吗

  • 您通常在不同的类之间创建友谊。这在语法上是有效的。为什么Peer是Peer的朋友
  • 私有函数只能由成员函数使用。从客户端代码调用它们是错误的
至于友谊是否会破坏封装的问题,请看下面的例子


抱歉,Robert,误读了名称。

在这种情况下不需要friend。类的对象可以访问相同类型的任何其他对象的私有成员。如果没有friend声明,它应该可以正常工作


不健康,它破坏了封装最佳实践

嗯,是和否

只有在不使用方法访问所需数据时,它才能破坏封装


不说封装只是保护外文类必须在你改变实现细节的情况下重写的一个方法。如果你碰巧改变了实现,你就必须重新修改你的类。

< P>标准C++表示私有子句具有类范围。这意味着每个对等体都可以访问私有部分O。这不是特定于实现的

尽管您发现在这种情况下不需要友谊,但我要说的是,与上述观点相反,合作类之间的友谊原则上没有任何问题。事实上,友谊并不是破坏封装,而是促进了友谊

考虑为私有数据创建一个访问器方法的替代方案。如果这样做,那么您将有效地访问所有客户端的私有数据,而不仅仅是声明为好友的有限的类/函数集。如果好友类中只有一个方法将访问您的内部封装减少了exa与提供公共访问器方法的数量完全相同。但是,提供公共访问器方法的结果将是更多的客户端将使用该方法

对于我们编写的每个应用程序类,都有一个影子类,即类单元测试。单元测试类是应用程序类的朋友,因为它经常需要调用类上的方法,然后检查类内部,或调用私有方法。作为朋友类,可以维护封装

无论如何,要进行良好的讨论,请参见此处:

首先,我想说的是,通过继承,好的类层次结构不需要为了复制构造函数或运算符重载等工作而公开私有数据。例如:

class Sub
    : public Base
{
public:
    Sub(const std::string & name)
        : Base(),
          m_name(name)
    {
    }

    Sub(const Sub & src)
        : Base(src),
          m_id(src.m_name)
    {
    }

    Sub & operator=(const Sub & rhs)
    {
        if (&rhs != this)
        {
            Base::operator=(rhs);

            m_name = rhs.m_name;
        }

        return (this);
    }

protected:
    virtual Debug(void)
    {
        std::cout << "Sub [m_name = " << m_name << "]" << std::endl
                  << "+- ";

        Base::Debug();
    }

private:
    std::string m_name;
};

class Base
{
public:
    Base(int id)
        : m_id(id)
    {
    }

    Base(const Base & src)
        : m_id(src.m_id)
    {
    }

    Base & operator=(const Base & rhs)
    {
        if (&rhs != this)
        {
            m_id = rhs.m_id;
        }

        return (this);
    }

protected:
    virtual Debug(void)
    {
        std::cout << "Base [m_id = " << m_id << "]" << std::endl;
    }

private:
    int m_id;
};
// This class defines an interface that allows selected classes to
// manipulate otherwise private data.
class SharedData
{
public:
    // Set some shared data.
    virtual void SettorA(int value) = 0;

    // Get some shared data.
    virtual bool GettorB(void) const;
};


// This class does something with the otherwise private data.
class Worker
{
public:
    void DoSomething(SharedData & data)
    {
        if (data.GettorB() == true)
        {
            data.SettorA(m_id);
        }
    }

private:
    int m_id;
};

// This class provides access to its otherwise private data to
// specifically selected classes.  In this example the classes
// are selected through a call to the Dispatch method, but there
// are other ways this selection can be made without using the
// friend keyword.
class Dispatcher
    : private SharedData
{
public:
    // Get the worker to do something with the otherwise private data.
    void Dispatch(Worker & worker)
    {
        worker.DoSomething(*this);
    }

private:
    // Set some shared data.
    virtual void SettorA(int value)
    {
        m_A = value;
    }

    // Get some shared data.
    virtual bool GettorB(void) const
    {
        return (m_B);
    }

    int    m_A;
    bool   m_B;
};
class子类
:公共基地
{
公众:
子(常量标准::字符串和名称)
:Base(),
m_姓名(姓名)
{
}
分包(施工分包和src)
:底座(src),
m_id(src.m_名称)
{
}
子运算符=(常量子运算符和rhs)
{
如果(&rhs!=此)
{
基::运算符=(rhs);
m_name=rhs.m_name;
}
返回(本);
}
受保护的:
虚拟调试(无效)
{

std::cout现在我已经讲了我关于继承的文章,这里有一些东西可能有助于解决你真正的问题,即如何避开友谊的潜在问题

我这样做的方式是创建一个纯粹的接口,用于访问我想与“朋友”共享的数据。然后我私下实现了这个接口,因此没有人可以直接访问它。最后,我有一些机制,允许我将接口的引用只传递给我想允许的那些选择类

例如:

class Sub
    : public Base
{
public:
    Sub(const std::string & name)
        : Base(),
          m_name(name)
    {
    }

    Sub(const Sub & src)
        : Base(src),
          m_id(src.m_name)
    {
    }

    Sub & operator=(const Sub & rhs)
    {
        if (&rhs != this)
        {
            Base::operator=(rhs);

            m_name = rhs.m_name;
        }

        return (this);
    }

protected:
    virtual Debug(void)
    {
        std::cout << "Sub [m_name = " << m_name << "]" << std::endl
                  << "+- ";

        Base::Debug();
    }

private:
    std::string m_name;
};

class Base
{
public:
    Base(int id)
        : m_id(id)
    {
    }

    Base(const Base & src)
        : m_id(src.m_id)
    {
    }

    Base & operator=(const Base & rhs)
    {
        if (&rhs != this)
        {
            m_id = rhs.m_id;
        }

        return (this);
    }

protected:
    virtual Debug(void)
    {
        std::cout << "Base [m_id = " << m_id << "]" << std::endl;
    }

private:
    int m_id;
};
// This class defines an interface that allows selected classes to
// manipulate otherwise private data.
class SharedData
{
public:
    // Set some shared data.
    virtual void SettorA(int value) = 0;

    // Get some shared data.
    virtual bool GettorB(void) const;
};


// This class does something with the otherwise private data.
class Worker
{
public:
    void DoSomething(SharedData & data)
    {
        if (data.GettorB() == true)
        {
            data.SettorA(m_id);
        }
    }

private:
    int m_id;
};

// This class provides access to its otherwise private data to
// specifically selected classes.  In this example the classes
// are selected through a call to the Dispatch method, but there
// are other ways this selection can be made without using the
// friend keyword.
class Dispatcher
    : private SharedData
{
public:
    // Get the worker to do something with the otherwise private data.
    void Dispatch(Worker & worker)
    {
        worker.DoSomething(*this);
    }

private:
    // Set some shared data.
    virtual void SettorA(int value)
    {
        m_A = value;
    }

    // Get some shared data.
    virtual bool GettorB(void) const
    {
        return (m_B);
    }

    int    m_A;
    bool   m_B;
};

在本例中,SharedData是一个接口,用于确定可以对数据执行哪些操作,即可以设置哪些操作,以及只能获取哪些操作。Worker是一个允许访问此特殊接口的类。Dispatcher私下实现该接口,因此访问Dispatcher实例不会授予您访问特殊接口的权限共享数据,但Dispatcher有一种方法允许工作人员访问。

我与我的任何同事都不是朋友。也许您希望在设计中采用不同的方法。例如,您的同事可能有一个负责您打算的行为的主控者。这在很大程度上取决于您尝试执行的操作。它会编译。GetSecret是public.GIveSeCeRT是私人的。当然,我在之前做了这个汇编,你是对的,友谊宣言是不必要的。我发誓我不能用一个相同的类对象来访问别人的私人方法。每天学习一些东西,即使经过很多年的C++!一个班永远是自己的朋友。