0

友達の機能を理解するためのデモプログラムがあります。前方宣言に関連するエラーで立ち往生していると思います。

xとyの座標を持つポイントクラスがあります。ラインクラスには、ポイントクラスの2つのオブジェクトがあります。これで、線の傾きを計算する線クラスの関数ができました。

これは私のプログラムです:

#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;
}

次の理由により、前方宣言に関してコンパイラエラーが発生します。

  1. 最初にラインクラスを定義しようとすると、ポイントクラスがわかりません。ポイントクラスのオブジェクトを作成するのに十分ではないポイントクラスを前方宣言したとしても、コンパイラはポイントクラスのサイズ、つまりクラス全体を知っている必要があります。この回答の説明を通してそれを理解しました:https ://stackoverflow.com/a/5543788

  2. 最初にポイントクラスを定義する場合、フレンド関数の傾き、つまりクラスラインを知る必要があります。そこで、ポイントクラスを定義する前に、ラインクラスとスロープ関数の前方宣言を次のように提供しようとしました。

クラスライン;

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のラインクラスを分離しようとしました。しかし、まだここには相互依存関係があります。

これは理論的には可能であるはずですが、どのように機能させるかはわかりません。

答えを探しています。

ありがとう、

ラージ

PS:このプログラムは、フレンド関数だけの使用法を示すための取り組みです。フレンド関数が2つのタイプである場合、これはこの種の2番目に対処するための取り組みです。

  1. 独立したフレンド機能。
  2. 別のクラスのメンバーであるフレンド関数。

したがって、この場合、フレンドクラスの使用は除外されます。

4

5 に答える 5

2

メソッドだけでなく、lineとして追加します。friend

 friend class line;

その他の注意:

  • ヘッダーファイルと実装ファイルの実装から宣言を分離します。
  • ディレクティブよりも完全な修飾を優先しますusing(つまり、代わりに削除using namespace std;して使用std::coutします。
  • 複合型には参照渡しを優先する-line(point,point);に変更line(const point&, const point&);

編集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してに変更します(ポイントはまだ完全なタイプではないため)。これでクラスの完全な定義ができたので、メソッドをフレンドとして宣言できます。pointlinepoint*pointline

編集2:この特定のシナリオでは、完全なタイプが必要になるため、point内部のオブジェクトを使用することはできません。lineただしline、そのメンバーをとして宣言するには、完全に定義する必要もありますfriend

于 2012-08-02T06:07:57.143 に答える
1

LineをPointの友達にするだけです

class point
{
 friend class line;
 ...
};

個々のメソッドを友達として宣言する目的はほとんどありません。

于 2012-08-02T06:07:35.403 に答える
1

通常の状況では、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


friendこれは、無料の関数(1.)のデモンストレーションです。

#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();
}

point内から参照するために、クラスはその時点で宣言されているが定義されlineていないため、 (auto_)ポインタと参照を使用します。私がそれをのとして参照するのに間に合うように宣言されています。この循環依存はひどいコードの臭いであり、避ける必要があります。line::slope()friendpoint

于 2012-08-02T06:15:03.320 に答える
1

勾配を計算するためのヘルパーファンクターを作成できます。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);
}
于 2012-08-02T06:20:20.373 に答える
0

friend float line::slope();クラスを定義する前に、でラインクラスを参照します。

class line;Pointクラスの定義の前に行を追加するだけです

また、に変更friend float line::slope();しますfriend class line;

于 2012-08-02T06:04:46.880 に答える