我的两个班级之间的朋友功能有问题。让我们看一些代码:
头等舱:
#ifndef _FIRST_H_
#define _FIRST_H_
//#include "Second.h"
#include <string>
class Second;
class First
{
friend void Second::fun();
std::string str = "Dziala\n";
public:
First();
~First();
};
#endif
和第二课:
#ifndef _SECOND_H_
#define _SECOND_H_
#include<iostream>
#include "First.h"
class Second
{
First fObj;
public:
Second();
~Second();
void fun() { std::cout << fObj.str; }
};
#endif
如果我想交朋友CLASS,没有问题。如果我像上面的例子中那样建立朋友FUNCTION,就会出现问题。 我可以通过First类中的#include“Second.h”来解决这个问题,但接下来它将是include循环。你知道怎么做吗?
答案 0 :(得分:2)
如果我像上面的例子那样交朋友FUNCTION,就会出现问题。
// #include "Second.h"
#include <string>
class Second;
class First
{
friend void Second::fun();
...
第一行是类Second
的声明。这是前瞻声明。对于课程Second
,在其声明之后及其定义之前,它是不完整类型。因此Second
被称为类类型,但它包含的成员是未知的。所以你不能在这里使用成员void Second::fun()
。
friend class Second
工作正常,因为它从不尝试使用不完整类型的成员。
然后它将是包含循环。
正如MadsMarquart所说,这不是问题,因为你已经有了头球卫士。
知道怎么做吗?
如果您想使用friend void Second::fun()
作为朋友声明,声明和定义的顺序很重要,只需对您的课程进行一些修改。
First
。Second
的声明(非定义)定义课程fun()
。
First fObj
成员或尝试new First
,因为First
未定义且First
的构造函数现在未知。 指针或引用就可以了。First
定义班级fun()
。fun()
。根据您的示例修改代码,
class First;
class Second {
public:
Second(First& rfObj) : fObj(rfObj) {}
void fun();
private:
First& fObj;
};
class First {
friend void Second::fun();
public:
First() = default;
private:
std::string str = "Dziala\n";
};
void Second::fun() { std::cout << fObj.str; }
答案 1 :(得分:0)
你知道怎么做吗?
您无法使用friend
机制来执行您正在尝试的操作。
一个简单的解决方案是通过成员函数公开First::str
,而不用担心friend
构造。从长远来看,这是一个更清洁的解决方案。
class First
{
public:
First();
~First();
std::string const& getString() const { return str; }
private:
std::string str = "Dziala\n";
};
答案 2 :(得分:0)
除非完整的类定义可见,否则无法将成员函数声明为朋友。否则允许任意代码声明和定义该类的创建者不想要的类的成员。
class Second // complete class definition, not just a forward declaration
{
public:
void fun();
};
class First
{
friend void Second::fun();
};
这样做的结果是First
不能仅仅是Second
的成员。为了接受这一点,编译器需要具有Second
的完整定义的可见性,以便编译First
的定义,同时还可以查看First
的完整定义以获得定义Second
编译。这是一种无限递归的依赖,这往往会扰乱编译器。
只能使用前向声明声明的类成员(或实际上通常是变量)的唯一类型是指针或引用。
所以,这会起作用
class First;
class Second // complete class definition, not just a forward declaration
{
private:
First &fObj; // note this is a reference
public:
void fun();
Second();
~Second();
};
class First
{
friend void Second::fun();
};
Second::Second() : fObj(*(new First)) // assumes First has appropriate (not shown) constructor
{}
Second::~Second()
{
delete &fObj;
}
但是,请注意,Second
的构造函数和析构函数也不能编译,除非First
的定义事先对编译器可见。这是因为不可能仅基于前向声明来创建或销毁类类型的实例(即与原始问题相同的原因)。
实际上,我只是宣布班级Second
是First
的朋友并完成它。毕竟,将一个类的一个成员函数声明为朋友断言,将始终实现成员函数以按预期工作。在极少数情况下,可以信任类的单个成员函数按要求工作,但不信任同一类的其他成员函数。