2012-05-11 88 views
13

根据C++ 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 C++ 2005)

回答

14

尝试把在B定义之前的:

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的前向声明。

+0

但是,如果在FB(A&一)我使用访问变量一种用于例如,a.variable;那将是非法的,因为A尚未确定。 – ipkiss

+1

@ipkiss是的,因为如果你在头类声明中需要完整的定义。但是如果你在一个单独的实现文件中完成它,你可以包含完整的声明A. – juanchopanza

2

为此,在定义A之前需要知道B的完整定义。

所以向前声明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(){} 
}; 
0

首先正确声明类A,以便它在B类定义中可见。然后使用一个特定的类名,你必须先声明它之前定义含B类

0

首先的一个友元函数类A。因此,在最初声明B类之前,您需要在B类中使用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尝试他们即使我们有一流的正向的声明,但是下面给出的代码将只是做工精细定义之前访问卷和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; 
} 
0

@juanchopanza @ipkiss 关于你不能访问内部FB的数据成员(A &一),因为还没有定义的问题。相反,在一个单独的文件中定义它,包括它的,你可以定义函数FB(一&一)A类的定义后,使得FB(一&一)能够看到A的数据成员

2

当编译器开始(通常从顶部)读取的代码,当它遇到这一行:

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

那么编译器不明白你说的这个意思B::。即使您稍后在代码中定义了此类,但编译器不知道这一点。所以如果定义稍后在代码中存在,那么通常练习做类的前向声明(class Name;)通常是一件好事。

2

当编译器开始编译代码(通常从上方)和它遇到这一行:

friend void B::fB(A& a); 
  1. 在这一点上,编译器不具有关于B的类型信息的想法,因此引发错误( 'B':不是类或名称空间名称)。
  2. 通过B类的前向声明,编译器知道B类的类型是事先对所有成员实际声明的类。

  3. 类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){}; 
}; 

还是错误后,下面的代码运行!

因为前向声明只是程序员尚未给出完整定义的标识符声明。因此编译器需要在A类之前完全定义B。

注意:类A的定义依赖于B的类型,还定义了B(即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的前向声明,我们可以让编译器知道A的类型信息。乙定义仅取决于A型所以A解析步骤的前向声明的不成员4.

  • 最终代码
  • ////// //////////////////

    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's 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's member function fB as a friend of A 
    }; 
    
    int main() 
    { 
        return 0; 
    } 
    
    +0

    那么,你如何解决这个练习? –

    +0

    @BrunoMartinez - 没有完美的解决方案,因为两者都是周期性地依赖于彼此的完整定义。给我这个特例的 的意图是强调解耦实体在软件设计中的重要性,并在处理这个问题的同时让Friend函数更清晰。 我想,你可能已经意识到可能的选择是创建一个共同的朋友功能 – SrinivasPaladugu

    相关问题