前向声明的问题-Friend函数和行/点类
Problems with forward declaration - Friend functions and line / point classes
我有一个演示程序来理解朋友函数。我想,我遇到了与正向声明相关的错误。
我有一个点类,它有x&y坐标。直线类有两个点类对象。现在我在line类中有一个函数,它将计算线的斜率。
这是我的程序:
#include <iostream>
using namespace std;
class point
{
int x,y;
public:
point(int,int);
point();
friend float line::slope();
};
point::point(int a, int b)
{
x=a;
y=b;
}
point::point()
{
}
class line
{
point p1,p2;
public:
line(point,point);
float slope();
};
line::line(point p1, point p2)
{
this->p1=p1;
this->p2=p2;
}
float line::slope()
{
float s;
s=((float)p2.y-p1.y)/(p2.x-p1.x);
return s;
}
int main()
{
float sl;
point obj(5,10);
point obj1(4,8);
line obj3(obj,obj1);
sl=obj3.slope();
cout<<"n slope:"<<sl;
return 0;
}
由于以下原因,它在前向声明方面给了我编译器错误:
当我尝试首先定义我的线类时,它不知道点类。即使我正向声明点类,这也不足以创建点类的对象,编译器应该知道点类的大小,从而知道整个类本身。通过这个答案中的解释来理解:https://stackoverflow.com/a/5543788
如果我首先定义点类,它需要知道友元函数的斜率,从而知道类线。因此,在定义点类之前,我尝试为直线类和斜率函数提供如下的正向声明:
等级线;
float line::slope(); class point { int x,y; public: point(int,int); point(); friend float line::slope(); };
现在这给了我以下错误:
friend1.cpp:5: error: invalid use of incomplete type ‘struct line’
friend1.cpp:4: error: forward declaration of ‘struct line’
friend1.cpp:13: error: invalid use of incomplete type ‘struct line’
friend1.cpp:4: error: forward declaration of ‘struct line’
friend1.cpp: In member function ‘float line::slope()’:
friend1.cpp:9: error: ‘int point::y’ is private
friend1.cpp:43: error: within this context
friend1.cpp:9: error: ‘int point::y’ is private
friend1.cpp:43: error: within this context
friend1.cpp:9: error: ‘int point::x’ is private
friend1.cpp:43: error: within this context
friend1.cpp:9: error: ‘int point::x’ is private
friend1.cpp:43: error: within this context
.3.接下来,我试图将point.h和point.cpp中的点类与line.h和line.cpp的行类分离。但这里仍然存在相互依赖关系。
虽然这在理论上应该是可能的,但我不知道如何让它发挥作用。
寻找答案。
谢谢,
Raj
PS:此程序旨在演示单独使用好友功能。当友元函数有两种类型时,这是为了处理第二种类型:
- 朋友功能是独立的
- 属于另一类的友元函数
因此,在这种情况下,排除了使用友元类的可能性。
将line
添加为friend
,而不仅仅是一个方法:
friend class line;
其他备注:
- 将声明与头文件和实现文件中的实现分开
- 与
using
指令相比,更喜欢完全限定(即删除using namespace std;
并改用std::cout
) - 更喜欢复杂类型的传递引用-将
line(point,point);
更改为line(const point&, const point&);
EDIT出于教育目的-您不能像现在的代码那样将特定函数声明为友元,因为line
类没有完整的定义。埃尔戈,以下是唯一的方法:
class point;
class line
{
point *p1,*p2;
public:
line(point,point);
float slope();
};
class point
{
int x,y;
public:
point(int,int);
point();
friend float line::slope();
};
您转发声明point
,并将line
中的point
成员更改为point*
(因为点还不是一个完整的类型)。在point
中,您现在拥有了line
类的完整定义,因此您可以将该方法声明为friend。
编辑2:对于这个特定的场景,不可能在line
中使用point
对象,因为您需要完整的类型。但是line
也必须被完全定义,才能将其成员声明为friend
。
让Line成为Point 的朋友
class point
{
friend class line;
...
};
将单个方法声明为朋友并没有什么意义。
您可以创建一个辅助函数来计算斜率。这允许您使函子的方法成为point
的朋友,而不涉及line
。
class point;
class line;
struct slope {
float operator () (const point &, const point &) const;
float operator () (const line &) const;
};
class point {
int x,y;
public:
point(int a,int b) : x(a), y(b) {}
point() {}
friend float slope::operator ()(const point &, const point &) const;
};
class line {
point p1,p2;
public:
line(point a,point b) : p1(a), p2(b) {}
float slope() { return ::slope()(*this); }
friend float slope::operator ()(const line &) const;
};
与实施:
float slope::operator () (const point &p1, const point &p2) const {
float s;
s=((float)p2.y-p1.y)/(p2.x-p1.x);
return s;
}
float slope::operator () (const line &l) const {
return (*this)(l.p1, l.p2);
}
在正常情况下,我会避免在这里使用friend
。
倾向于在point
:中添加一个函数
float slope_to(const point& other)
{// Not checked, just translated from your implementation
return ((float)other.y-y)/(other.x-x);
}
并实现:
float line::slope()
{
return p1.slope_to(p2);
}
这样line
就不关心point
的实现,并且在实现3D points
时也不需要更改。
以下是自由函数(1.):的friend
的演示
#include <iostream>
class point
{
int x, y;
public:
point(int, int);
friend std::ostream& operator <<(std::ostream& os, const point& p);
};
std::ostream& operator <<(std::ostream& os, const point& p)
{
return os << '(' << p.x << ", " << p.y << ')';
}
point::point(int a, int b)
:x(a)
,y(b)
{
}
int main()
{
point obj(5, 10);
std::cout << "n point " << obj;
}
下面是一个在您自己的代码上构建的示例,它具有成员函数(2.)的friend
#include <iostream>
#include <memory>
using namespace std;
class point;
class line
{
std::auto_ptr<point> p1, p2;
public:
line(point&, point&);
float slope();
};
class point
{
int x, y;
public:
point(int, int);
friend float line::slope();
};
point::point(int a, int b)
:x(a)
,y(b)
{
}
line::line(point& p1, point& p2)
:p1(new point(p1))
,p2(new point(p2))
{
}
float line::slope()
{
return ((float)p2->y - p1->y) / (p2->x - p1->x);
}
int main()
{
point obj(5, 10);
point obj1(4, 8);
line obj3(obj, obj1);
cout << "n slope:" << obj3.slope();
}
为了从line
中引用point
,我使用(auto_
)指针和引用,因为类在该点被声明,而不是定义。CCD_ 31被及时声明,以便我将其引用为CCD_ 33的CCD_。这种循环依赖是一种可怕的代码气味,应该避免。
在定义类之前,您引用了friend float line::slope();
中的行类。
只需在点类的定义之前添加线class line;
也将friend float line::slope();
更改为friend class line;
- 如何通过派生类函数更改基类中的向量
- 库函数需要一个 std::function<void(void)>,如何传入类函数?
- 在类函数中初始化外部作用域变量
- c++ 在非类函数中使用类变量
- SDL_PollEvent() 无法捕获类函数内部SDL_QUIT?
- 从类成员函数到类 C 函数指针的转换
- 如何在模板类函数中分配结构值?
- 有没有办法将重载的类函数绑定到函数对象?
- 启动类函数作为失去引用的线程
- C++调用使用重写函数的父类函数
- 将值传递到另一个类函数在打印时为零
- 计算对类函数的所有调用次数
- 由于签名差异,调用了错误的子类函数
- 使用宏调用类函数
- 虚拟基类函数中派生类的大小
- 模板类/函数中的交叉前向声明
- 在C++中使用非静态类函数的函数
- 前向声明的问题-Friend函数和行/点类
- "has-a"点类成员数据的矩形类。使用 Point 类的成员函数时,成员数据不会更新
- 点击按钮 -> 执行我在参数中给出的任何类函数 (C++)