14

私は言語を学ぶ過程にあり、これは間違いありません。

仮想フレンド機能を使用することはできますか?それが可能かどうかはわかりません。テストもしていませんが、状況によっては役立つ可能性があります。たとえば、オーバーロードされた演算子<<()の場合。

DerivedClass dc;
BaseClass &rbc = dc;
cout << rbc;

私の推測では可能ですが、フレンド関数はクラス設計に実装されておらず、理論的にはその一部ではないため、わかりません(ただし、この例では、概念的には、operator <<()がメソッドですが、構文上の制限により、1つとして実装することはできません)。

編集:私の懸念はこの例に関連しています:

BaseClass bc;
DerivedClass dc;
BaseClass *pArr[2];
pArr[1] = bc;
pArr[2] = dc;
for (int i = 0; i < 2; i++)
    cout << pArr[i];

この混合オブジェクトの配列では、それぞれに対して正しい演算子<<()を呼び出す必要があります。

4

5 に答える 5

42

いいえ、friend virtual関数はまったく意味がありません。

friendprivate関数はそのようなものであり、メソッド(別名メンバー関数)ではなく、のprotectedメンバーにアクセスする権利がありますclass

virtual関数はメンバー関数のみになります。virtual非会員機能を持つことはできません。


operator<<基本クラスへの参照を取得してから、いくつかのvirtualメンバー関数を呼び出すことができます。operator<<このようにして、 「ほぼ仮想」にすることができます:)


例えば

class A
{
public:
    virtual void f() const { std::cout << "base"; }
};
class B: public A
{
public:
    virtual void f() const { std::cout << "derived"; }
};

std::ostream& operator<<(std::ostream& os, const A& a )
{
     a.f();
     return os;
}

int main()
{
    B b;
    std::cout << b << std::endl;

    return 0;
}

印刷しますderived

于 2012-08-27T13:28:25.713 に答える
13

バーチャルフレンド機能イディオム

C ++のフレンド関数は仮想として宣言できないため、フレンド関数を動的にバインドすることはできません。階層内のすべてのクラスにオーバーロードされたフレンド関数が必要な場合、クラスの階層全体にフレンド関数を適用するのは厄介になります。この動的バインディングのサポートの欠如により、それが実際にはクラスのインターフェースの拡張であることを正当化することは困難です。仮想フレンド関数イディオムは、この懸念にエレガントに対処します。

仮想フレンド関数イディオムを使用する必要があります。要点は、仮想関数をBaseに保持し、友人関数にその関数を呼び出させることです。これは、派生クラスのその関数を多形的に呼び出します

リンクから直接例をコピーする

class Base {
  public:
    friend ostream& operator << (ostream& o, const Base& b);
  protected:
    virtual void print(ostream& o) const{ ... }
};
/* make sure to put this function into the header file */
inline std::ostream& operator<< (std::ostream& o, const Base& b){
  b.print(o); // delegate the work to a polymorphic member function.
  return o;
}

class Derived : public Base {
  protected:
    virtual void print(ostream& o) const{ ... }
};
于 2012-08-27T13:30:35.157 に答える
6

パブリック仮想メソッドのみを使用して、フレンド関数なしでこれを解決できます。

struct BaseClass {
  virtual void print(std::ostream& os) const;
};

struct DerivedClass {
  virtual void print(std::ostream& os) const;
};

std::ostream& operator<<(std::ostream& os, const BaseClass& obj) {
  obj.print(os);
  return os;
}

printメソッドをパブリックにすることが意味をなさない場合は、ostream& operator<<をとして宣言できますfriend

于 2012-08-27T13:34:00.947 に答える
1

仮想関数は、フレンド関数以外のものです。仮想関数は、1つのクラスを基本クラスとして、もう1つのクラスを派生クラスとしてプログラムで継承を使用する場合にのみ使用されます。仮想関数は、オブジェクトの動的バインディングに使用されます。これは、派生クラスのオブジェクトを基本クラスのポインターに格納し、その特定の派生クラスのメソッドを呼び出すことができることを意味します。この概念はポリモーフィズムとして知られています。

フレンド関数は、クラスのプライベートインターフェイスにアクセスするために使用されます。クラスで継承が使用されていない場合でも、これらを使用できます。

于 2012-08-27T13:29:03.090 に答える
1

同じクラスの友達と仮想関数の両方になることはできません。ただし、フレンドオペレーターは、印刷しているオブジェクトから仮想関数を呼び出すことができます。

ostream& operator<<(ostream& stream, const BaseClass& rbc)
{
    rbc.print_on(stream);
    return stream;
}
于 2012-08-27T13:32:18.020 に答える