简体   繁体   English

C ++朋友类和朋友成员函数

[英]C++ friend classes and friend member functions

I'm learning about friend functions, friend classes and friend member functions in C++ classes; 我正在学习C ++类中的朋友函数,朋友类和朋友成员函数。 Now, the following code compiles fine: 现在,以下代码可以正常编译:

#include <iostream>

class A 
{
public:
    friend class B;
    //friend void B::set(int i);
    //friend int B::get();
    friend int function(A a);
    A(int i);
    void set(int i);
    int get();
private:
    int i;
};

A::A(int i) : i(i)
{
}

void A::set(int i)
{
    this->i = i;
}

int A::get()
{
    return i;
}

class B
{
public:
    B(A a);
    void set(int i);
    int get();
private:
    A a;
};

B::B(A a) : a(a)
{
}

void B::set(int i)
{
    a.i = i;
}

int B::get()
{
    return a.i;
}

int function(A a);

int main(int argc, char *argv[])
{
    A a(0);
    std::cout << "in A i=" << a.get() << std::endl;
    a.set(10);
    std::cout << "in A i=" << a.get() << std::endl;
    B b(a);
    std::cout << "in B i=" << b.get() << std::endl;
    b.set(21);
    std::cout << "in B i=" << b.get() << std::endl;
    std::cout << "function returns " << function(a) << std::endl;
}

int function(A a)
{
    return a.i;
}

I am able to grant friendship to class B and to function "function" in class A without forward declaring class B, or function "function". 我能够向B类授予友谊,并能够在A类中行使“功能”,而无需预先声明B类或功能“功能”。 Now, if I want to grant friendship to the two member functions in class B it doesn't work if I don't define class B before defining class A: 现在,如果我想给类B中的两个成员函数赋予友谊,那么如果在定义类A之前不定义类B,那将是行不通的:

#include <iostream>

class B;   // doesn't work, incomplete type (complete type needed)

class A 
{
public:
    //friend class B;
    friend void B::set(int i);
    friend int B::get();
    friend int function(A a);
    A(int i);
    void set(int i);
    int get();
private:
    int i;
};

A::A(int i) : i(i)
{
}

void A::set(int i)
{
    this->i = i;
}

int A::get()
{
    return i;
}

B::B(A a) : a(a)
{
}

void B::set(int i)
{
    a.i = i;
}

int B::get()
{
    return a.i;
}

int function(A a);

int main(int argc, char *argv[])
{
    A a(0);
    std::cout << "in A i=" << a.get() << std::endl;
    a.set(10);
    std::cout << "in A i=" << a.get() << std::endl;
    B b(a);
    std::cout << "in B i=" << b.get() << std::endl;
    b.set(21);
    std::cout << "in B i=" << b.get() << std::endl;
    std::cout << "function returns " << function(a) << std::endl;
}

int function(A a)
{
    return a.i;
}

but I can't define class B before defining class A so I'm stuck. 但是我无法在定义类A之前定义类B,所以我陷入了困境。 Forward declaring (not defining) class B doesn't work either. 前向声明(未定义)B类也不起作用。

So my questions are: 所以我的问题是:

1) why I dont need to forward declare a function or an entire class in a friendship declaration but I do need to define a class if I need to specify member functions of that class? 1)为什么我不需要在友谊声明中转发声明一个函数或整个类,但是如果我需要指定该类的成员函数,则需要定义一个类? I know that friendship declarations are not declarations in the common sense (they just grant access, they don't forward declare anything). 我知道友谊声明不是常识声明(它们只是授予访问权限,它们不会转发任何声明)。

2) how can I make my code compile (besides declaring the A member object in B as A *a)? 2)如何使我的代码编译(将B中的A成员对象声明为A * a)?

Here is an example of a friend class and how to use it. 这是一个朋友类的示例以及如何使用它。 This was taken cplusplus.com The reason I am posting this is because your example does not really illustrate the proper use of friendship in c++. 这是在cplusplus.com上获得的 。我之所以这样发布是因为您的示例并未真正说明c ++中友谊的正确使用。 I hope this will shed some light as to how/why you should use friendship, and that can lead to you solving your forward declaration problems. 我希望这将为您说明如何/为什么使用友谊,这可以导致您解决前向声明问题。

// friend class
#include <iostream>
using namespace std;

class Square;

class Rectangle {
    int width, height;
  public:
    int area ()
      {return (width * height);}
    void convert (Square a);
};

class Square {
  friend class Rectangle;
  private:
    int side;
  public:
    Square (int a) : side(a) {}
};

void Rectangle::convert (Square a) {
  width = a.side;
  height = a.side;
}

int main () {
  Rectangle rect;
  Square sqr (4);
  rect.convert(sqr);
  cout << rect.area();
  return 0;
}

In this example, class Rectangle is a friend of class Square allowing Rectangle's member functions to access private and protected members of Square. 在此示例中,Rectangle类是Square类的朋友,允许Rectangle的成员函数访问Square的私有成员和受保护成员。 More concretely, Rectangle accesses the member variable Square::side, which describes the side of the square. 更具体地说,Rectangle访问成员变量Square :: side,该变量描述正方形的侧面。

There is something else new in this example: at the beginning of the program, there is an empty declaration of class Square. 此示例中还有其他新内容:在程序的开头,有一个空的Square类声明。 This is necessary because class Rectangle uses Square (as a parameter in member convert), and Square uses Rectangle (declaring it a friend). 这是必需的,因为类Rectangle使用Square(作为成员转换中的参数),而Square使用Rectangle(将其声明为朋友)。

Friendships are never corresponded unless specified: In our example, Rectangle is considered a friend class by Square, but Square is not considered a friend by Rectangle. 除非指定,否则从不建立友谊:在我们的示例中,Square将Rectangle视为朋友类,但Rectangle不将Square视为朋友。 Therefore, the member functions of Rectangle can access the protected and private members of Square but not the other way around. 因此,Rectangle的成员函数可以访问Square的受保护成员和私有成员,但不能相反。 Of course, Square could also be declared friend of Rectangle, if needed, granting such an access. 当然,如果需要,也可以将Square声明为Rectangle的朋友,以授予此类访问权限。

Another property of friendships is that they are not transitive: The friend of a friend is not considered a friend unless explicitly specified. 友谊的另一个特性是,它们不是可传递的:除非明确指定,否则朋友的朋友不会被视为朋友。

Just make class B a friend of class A . 只是让class B class A class B的朋友。 There are no adverse effects in doing this. 这样做没有不利影响。

If you absolutely positively want to exercise more fine-grained control, you can do it with a proxy class like this (using your example stripped to bare bones): 如果您绝对肯定要行使更细粒度的控制,则可以使用这样的代理类来做到这一点(使用剥离了示例的示例):

class Proxy;

class A
{
public:
    friend class Proxy;
    A(int i);
private:
    int i;
};

class B
{
public:
    B(A a);
    void set(int i);
    int get();
private:
    A a;
};

class Proxy
{
  friend void B::set(int);
  friend int B::get();
  static int& get_i(A& a) { return a.i; }
  static const int& get_i(const A& a) { return a.i; }
};

You now can use Proxy::get_i(a) instead of ai in B::set and B::get (only). 现在,您可以在B::setB::get (仅)中使用Proxy::get_i(a)代替ai

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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