Подтвердить что ты не робот

Укажите функцию члена класса как друга другого класса?

Согласно книге С++ Primer, автор упомянул, что мы можем указать функцию члена класса как друга другого класса, а не весь класс (стр. 634).

Затем я протестировал этот код:

class A
{
public:
    friend void B::fB(A& a);
    void fA(){}
};
class B
{
public:
    void fB(A& a){};
    void fB2(A& a){};
};

Я просто хотел, чтобы fB() был другом класса A, а не всего класса B. Но в коде произошла ошибка: 'B' : is not a class or namespace name. (Я использую Visual С++ 2005)

4b9b3361

Ответ 1

Попробуйте поставить определение B перед A:

class A; // forward declaration of A needed by B

class B
{
public:
    // if these require full definition of A, then put body in implementation file
    void fB(A& a); // Note: no body, unlike original.
    void fB2(A& a); // no body.
};

class A
{
public:
    friend void B::fB(A& a);
    void fA(){}
};

A требуется полное определение B. Тем не менее, B должен знать о A, но не нуждается в полном определении, поэтому вам нужно объявление вперед A.

Ответ 2

Для этого необходимо определить полное определение B до определения A.

Итак, вперед объявите A, так как B не нужен полный тип и переключите определения вокруг:

class A;
class B
{
public:
    void fB(A& a){};
    void fB2(A& a){};
};
class A
{
public:
    friend void B::fB(A& a);
    void fA(){}
};

Ответ 3

Когда компилятор начинает читать код (обычно сверху), и он встречает эту строку:

friend void B::fB(A& a);

Тогда компилятор не понимает, что вы подразумеваете под этим B::. Даже если вы определили этот класс позже в коде, но компилятор этого не знает. Поэтому обычно полезно практиковать, чтобы сделать декларацию объявления класса (class Name;), если определение будет указано позже в коде.

Ответ 4

Когда компилятор начинает компилировать код (обычно сверху) и сталкивается с этой строкой:

friend void B::fB(A& a);
  • в этот момент компилятор понятия не имеет о типе информации B, поэтому он выдает ошибку ( "B": не является именем класса или пространства имен).
  • путем прямого объявления класса B, компилятор знает о типе B, является классом перед его фактическим объявлением со всеми членами.

  • запускается под кодом после прямого объявления класса B.

///////////////

class B;
class A
{
public:
    friend void B::fB(A& a); 
    void fA(){};
};
class B
{
public:
    void fB(A& a){};
    void fB2(A& a){};
};

Еще ошибка!!!

потому что форвардное объявление - это просто объявление идентификатора, для которого программист еще не дал полного определения. поэтому компилятору необходимо полное определение B перед классом A.

Примечание. Идентификаторы определения класса A по типу B, а также определение B (i.e B:: fB), так что одно только декларацию объявления не может быть разрешено, полное определение класса B необходимо определить перед классом A.

4 запустите этот код

////////

class B
{
public:
    void fB(A& a){};
    void fB2(A& a){};
};
class A
{
public:
    friend void B::fB(A& a); 
    void fA(){}
};

Еще ошибка!!!

поскольку функции-члены класса B fB и fB2 имеют аргументы типа A, но компилятор понятия не имеет о типе информации A, поэтому путем прямого объявления класса A мы можем сообщить компилятору о типе info A. Примечание: определение класса B зависит только от типа A, а не от членов A, так что форвардное объявление A разрешает шаг 4.

  1. окончательный код

////////////////////////

class A;  // forward declaration of A needed by B
class B
{
public:
    void fB(A& a);
};

class A
{
    int i;
public:
    friend void fA(A& a);    //specifying function fA as a friend of A, fA is not member function of A
    friend void B::fB(A& a); //specifying B class member function fB as a friend of A
};

// fA is Friend function of A
void fA(A& a)
{
    a.i  = 11; // accessing and modifying Class A private member i
    cout<<a.i<<endl;
}

// B::fB should be defined after class A definition only because this member function can access Class A members
void B::fB(A& a)
{
    a.i  = 22; // accessing and modifying Class A private member i in Class B member function fB
    cout<<a.i<<endl;
}

int main()
{
    A a;
    fA(a);    // calling friend function of class A

    B b;
    b.fB(a);  // calling B class member function fB, B:fB is friend of class A

    return 0;
}

6 Упражнение:

// Cyclic dependency 
#include<iostream>
using namespace std;

class A;

class B
{
public:
    void fB(A& a);
    friend void A::fA(B& b); //specifying class A member function fA as a friend of B
};

class A
{
    int i;
public:
    void fA(B& b);  
    friend void B::fB(A& a); //specifying class B member function fB as a friend of A
};

int main()
{
    return 0;
}

Ответ 5

сначала вперед объявить класс A, чтобы его было видно в определении класса B. затем определите класс A, содержащий функцию друга из класса B.

Ответ 6

Прежде всего, прежде чем использовать конкретное имя класса, вам придется сначала объявить его. Таким образом, вам понадобится переадресация класса B, поскольку вы используете его в классе A до того, как изначально был объявлен класс B.

Во-вторых, вам нужно будет определить функции (которые используют переменные из обоих классов - здесь функции друга) после того, как оба класса определены. Или мы можем столкнуться с ошибками.

Например

#include<iostream>

using namespace std;

class alpha1;

class alpha2
{
    public:

        void put_bata(int a,int b);
};

void alpha2 :: put_bata(int a,int b)
{
    alpha1 net;

    net.roll=a;

    net.id=b;

    net.get_data();
}

class alpha1
{
    int roll;

    int id;

    public:

        void get_data(void)
        {
            cout<<roll<<endl<<id<<endl;
        }

        friend void alpha2 :: put_bata(int a,int b);
};

int main()
{
    alpha2 gamma;

    gamma.put_bata(5,6);

    return 0;
}

Покажет нам ошибки, так как put_bata пытается получить доступ к roll и id до того, как они будут определены, даже если у нас было объявление вперед класса, но приведенный ниже код будет работать нормально.

#include<iostream>

using namespace std;

class alpha1;

class alpha2
{
    public:

        void put_bata(int a,int b);
};

class alpha1
{
    int roll;

    int id;

    public:

        void get_data(void)
        {
            cout<<roll<<endl<<id<<endl;
        }

        friend void alpha2 :: put_bata(int a,int b);
};

void alpha2 :: put_bata(int a,int b)
{
    alpha1 net;

    net.roll=a;

    net.id=b;

    net.get_data();
}


int main()
{
    alpha2 gamma;

    gamma.put_bata(5,6);

    return 0;
}

Ответ 7

@juanchopanza @ipkiss Что касается проблемы, в которой вы не можете получить доступ к элементам данных A внутри fB (A & a), поскольку A еще не определен. Вместо определения его в отдельном файле и его включении, вы можете просто определить функцию fB (A & a) после определения класса A, чтобы fB (A & a) мог видеть элементы данных A.