none
关于友元关系,出现一个奇怪的问题 RRS feed

  • 问题

  • 今天进行关于友元friend代码测试的时候发现的一个问题。

    测试环境:Visual studio 2012

    测试代码段1:

    // classes_as_friends1.cpp
    #include <iostream>
    
    //using namespace std;
    // compile with: /c
    class B;
    
    class A {
    public:
    	int Func1( B& b );
    
    private:
    	int Func2( B& b );
    };
    
    class B {
    	friend int A::Func1( B& );
    private:
    	int _b;
    
    	// A::Func1 is a friend function to class B
    	// so A::Func1 has access to all members of B
    	//friend int A::Func1( B& );
    };
    
    int A::Func1( B& b ) { return b._b; }   // OK
    //int A::Func2( B& b ) { return b._b; }   // error C2248
    
    int main()
    {
    	A obj1;
    	B obj2;
    	obj1.Func1(obj2);
    
    	return 0;
    }
    
    
    

    上面的代码段中“b._b”在VS2012中提示语法类错误,但是可以进行正常编译和运行。

    注:此段代码未经任何影响结果的修改。

    测试代码段2:

    // 友元类成员函数不好使
    
    #ifndef DEBUG
    #define DEBUG
    
    #include <iostream>
    
    using namespace std;
    
    class ClassB;
    
    class ClassA
    {
    	friend int ClassB::set_value(ClassA);  //提示错误
    	friend int ClassB::get_value(ClassA);
    private:
    	int varA;
    public:
    };
    class ClassB
    {
    	//friend int ClassB::set_value(ClassA);
    	//friend int ClassB::get_value(ClassA);
    private:
    	int varB;
    public:
    	int set_value(ClassA);
    	int get_value(ClassA);
    };
    int ClassB::set_value(ClassA objA)
    {
    	int temp(0);
    	this->varB = objA.varA;
    	temp = objA.varA;
    	return temp;
    }
    int ClassB::get_value(ClassA objA)
    {
    	int temp = this->set_value(objA);
    	return temp;
    }
    class ClassC : public ClassA
    {
    private:
    public:
    };
    
    int main()
    {
    	return 0;
    }
    
    #endif //!DEBUG

    上面代码段中“this->varB = objA.varA;”提示语法错误,并且在VS2012中无法正常编译通过。

    注:此段测试代码完全仿照代码段2进行编写。

    问题:类似的代码段却出现不同的问题,真是令我很费解,不知道有没有人有兴趣一起跟我研究下原因。

    另外,上面的代码把“friend int ClassB::set_value(ClassA);” 换成“friend class ClassB;”就可以正常通过编译并且运行。


    煮酒论英雄

    2013年2月17日 13:34

答案

  • 修改了一下,这样就可以编译过去了:
    using namespace std;
    class ClassA;
    class ClassB
    {
    	//friend int ClassB::set_value(ClassA);
    	//friend int ClassB::get_value(ClassA);
    private:
    	int varB;
    public:
    	int set_value(ClassA);
    	int get_value(ClassA);
    };
    class ClassA
    {
    	friend int ClassB::set_value(ClassA);  //提示错误
    	friend int ClassB::get_value(ClassA);
    private:
    	int varA;
    public:
    };
    int ClassB::set_value(ClassA objA)
    {
    	int temp(0);
    	this->varB = objA.varA;
    	temp = objA.varA;
    	return temp;
    }
    int ClassB::get_value(ClassA objA)
    {
    	int temp = this->set_value(objA);
    	return temp;
    }
    class ClassC : public ClassA
    {
    private:
    public:
    };
    int main()
    {
    	return 0;
    }


    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.

    2013年2月18日 3:52
    版主
  • 你可以做这样一个小测试:

    在VisualEleven修改过的那段代码中,在A类中添加一个函数,并将这个函数作为B类的友元函数,则编译失败。

    根据这个测试结果,我认为,如果你把B类的成员函数作为A类的友元函数,则B类的定义必须在A类之前,仅仅做前置声明是不够的。


    Damon Zheng
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2013年2月21日 17:45
    版主

全部回复

  • 友元函数不能是类的成员函数


    麻烦把正确答案设为解答。

    2013年2月18日 2:42
    版主
  • C++ 友元成员: 一个类的成员函数可以作为另一个类的友元,这种成员函数称为友元函数成员。

    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.

    2013年2月18日 3:48
    版主
  • 修改了一下,这样就可以编译过去了:
    using namespace std;
    class ClassA;
    class ClassB
    {
    	//friend int ClassB::set_value(ClassA);
    	//friend int ClassB::get_value(ClassA);
    private:
    	int varB;
    public:
    	int set_value(ClassA);
    	int get_value(ClassA);
    };
    class ClassA
    {
    	friend int ClassB::set_value(ClassA);  //提示错误
    	friend int ClassB::get_value(ClassA);
    private:
    	int varA;
    public:
    };
    int ClassB::set_value(ClassA objA)
    {
    	int temp(0);
    	this->varB = objA.varA;
    	temp = objA.varA;
    	return temp;
    }
    int ClassB::get_value(ClassA objA)
    {
    	int temp = this->set_value(objA);
    	return temp;
    }
    class ClassC : public ClassA
    {
    private:
    public:
    };
    int main()
    {
    	return 0;
    }


    Visual C++ enthusiast, like network programming and driver development. At present is being engaged in the WinCE/Windows Mobile platform embedded development.

    2013年2月18日 3:52
    版主
  • 但是测试代码段1中“friend int A::Func1( B& );”是累的成员函数, 编译也能通过,是不是说编译器有问题?


    煮酒论英雄

    2013年2月19日 14:45
  • 非常感谢VisualEleven的解答,在vs2012上编译可以通过了,但是Vs2012还是会提示语法错误,看来这个问题是顺序问题,以后还是少用类的成员函数做友元函数比较好,避免出错。

    煮酒论英雄

    2013年2月19日 14:54
  • 你可以做这样一个小测试:

    在VisualEleven修改过的那段代码中,在A类中添加一个函数,并将这个函数作为B类的友元函数,则编译失败。

    根据这个测试结果,我认为,如果你把B类的成员函数作为A类的友元函数,则B类的定义必须在A类之前,仅仅做前置声明是不够的。


    Damon Zheng
    MSDN Community Support | Feedback to us
    Develop and promote your apps in Windows Store
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    2013年2月21日 17:45
    版主