zoukankan      html  css  js  c++  java
  • c++ two classes as each others' friends

    In this case, Box need access to Cup.func, AND Cup need access to Box.func, both of which are private because I don't want any other class to have access to neither Box.func nor Cup.func.

    So they need to declare each other as friend. 

    Suppose you organise code like Box1.h, Box1.cpp, Cup1.h, Cup1.cpp, it would cause a problem like this: http://www.cnblogs.com/qrlozte/p/4099032.html

    The compiler will complain. So the solution is also simple, see Cup2.h, Cup2.cpp, other files remain unchanged. (Of couse, you can change Box1.h Box1.cpp using the same pattern as Cup2.h Cup2.cpp, although it would make your code looks more consistent, but only changing Cup1.h, Cup1.cpp is already enough to satisfy your need.)

    Another question, what if Box.doSomething is a function template? If you change main1.cpp to main2.cpp, and Box1.h, Box1.cpp to Box2.h, Box2.cpp, the linker will complain that it cannot find the implementation of Box.doSomething (undefined reference error) (after all, the compiler need all the detail of a template to generate code, if you hide the implementation of Box.doSomething in Box2.cpp, how can you expect the compiler can generate code for Box.doSomething<int>() in main2.cpp when main2.cpp doesn't include Box2.cpp, right?).

    So, because function template (and class template) must define (just declare is NOT enough) in the header, you might modify Box2.h and Box2.cpp as shown in Box3.h and Box3.cpp. And you'll find the problem is solved! (Now we got main2.cpp, Box3.h, Box3.cpp, Cup2.h, Cup2.cpp compiled successfully).

    Now consider what if Cup.doSomething also need to be a function template? (The same as Box.doSomething in Box3.h). And... yes, you have to include the definition of Cup.doSomething in Cup.h, too!

    And you if you that, the compiler will complain Box is an incomplete type thus in Cup.doSomething, "b.func" cannot be resolved. As shown in main3.cpp, Cup3.h, Cup3.cpp.

    The reason is because in Cup3.h "class Box;" it indeed declares class Box, but just the class name, no information is provided about the interface of the class at all. 

    Can you replace "class Box;" with "#include "Box.h"" ? No. Because that'll cause the same problem as Box1.h, Box1.cpp, Cup1.h, Cup1.cpp caused.

    The solution ? At least for now, I don't know(If I can seperate Cup.doSomething() into two parts, one part is template and one part is normal function and the template part doesn't have to access memebers of the parameter 'b', then there's a simple solution, just let the template part in the header, and implement the normal function in Cup.cpp). This situation is not made up by me, I really encountered this problem when I was making a little program. Maybe there's something wrong with my design.

    main1.cpp

     1 #include "Box.h"
     2 #include "Cup.h"
     3 
     4 int main()
     5 {
     6     Cup c;
     7     Box b;
     8     c.doSomething(b);
     9     b.doSomething(c);
    10     return 0;
    11 }

    Box1.h

     1 #ifndef BOX_H
     2 #define BOX_H
     3 
     4 #include "Cup.h"
     5 
     6 class Box
     7 {
     8     friend class Cup;
     9     public:
    10         Box();
    11         ~Box();
    12         void doSomething(const Cup &c);
    13     private:
    14         void func() const;// only visible to Cup
    15 };
    16 
    17 #endif // BOX_H

    Box1.cpp

     1 #include "Box.h"
     2 
     3 #include <iostream>
     4 
     5 Box::Box()
     6 {
     7 
     8 }
     9 Box::~Box()
    10 {
    11 
    12 }
    13 void Box::doSomething(const Cup &c)
    14 {
    15     c.func();
    16 }
    17 void Box::func() const
    18 {
    19     using namespace std;
    20     cout << "Box.func" << endl;
    21 }

    Cup1.h

     1 #ifndef CUP_H
     2 #define CUP_H
     3 
     4 #include "Box.h"
     5 
     6 class Cup
     7 {
     8     friend class Box;
     9     public:
    10         Cup();
    11         ~Cup();
    12         void doSomething(const Box &b);
    13     private:
    14         void func() const; // only visible to Box
    15 };
    16 
    17 #endif // CUP_H

    Cup1.cpp

     1 #include "Cup.h"
     2 
     3 #include <iostream>
     4 
     5 Cup::Cup()
     6 {
     7 
     8 }
     9 Cup::~Cup()
    10 {
    11 
    12 }
    13 void Cup::doSomething(const Box &b)
    14 {
    15     b.func();
    16 }
    17 
    18 void Cup::func() const
    19 {
    20     using namespace std;
    21     cout << "Cup.func" << endl;
    22 }

    Cup2.h

     1 #ifndef CUP_H
     2 #define CUP_H
     3 
     4 class Box;
     5 
     6 class Cup
     7 {
     8     friend class Box;
     9     public:
    10         Cup();
    11         ~Cup();
    12         void doSomething(const Box &b);
    13     private:
    14         void func() const; // only visible to Box
    15 };
    16 
    17 #endif // CUP_H

    Cup2.cpp

     1 #include "Cup.h"
     2 
     3 #include "Box.h"
     4 
     5 #include <iostream>
     6 
     7 Cup::Cup()
     8 {
     9 
    10 }
    11 Cup::~Cup()
    12 {
    13 
    14 }
    15 void Cup::doSomething(const Box &b)
    16 {
    17     b.func();
    18 }
    19 
    20 void Cup::func() const
    21 {
    22     using namespace std;
    23     cout << "Cup.func" << endl;
    24 }

    main2.cpp

     1 #include "Box.h"
     2 #include "Cup.h"
     3 
     4 int main()
     5 {
     6     Cup c;
     7     Box b;
     8     c.doSomething(b);
     9     b.doSomething<int>(1, c);
    10     return 0;
    11 }

    Box2.h

    #ifndef BOX_H
    #define BOX_H
    
    #include "Cup.h"
    
    class Box
    {
        friend class Cup;
        public:
            Box();
            ~Box();
            template <typename T> void doSomething(const T &obj, const Cup &c);
        private:
            void func() const;// only visible to Cup
    };
    
    #endif // BOX_H

    Box2.cpp

     1 #include "Box.h"
     2 
     3 #include <iostream>
     4 
     5 Box::Box()
     6 {
     7 
     8 }
     9 Box::~Box()
    10 {
    11 
    12 }
    13 template <typename T> void doSomething(const T &obj, const Cup &c)
    14 {
    15     c.func();
    16 }
    17 void Box::func() const
    18 {
    19     using namespace std;
    20     cout << "Box.func" << endl;
    21 }

    Box3.h

     1 #ifndef BOX_H
     2 #define BOX_H
     3 
     4 #include "Cup.h"
     5 
     6 class Box
     7 {
     8     friend class Cup;
     9     public:
    10         Box();
    11         ~Box();
    12         template <typename T> void doSomething(const T &obj, const Cup &c);
    13     private:
    14         void func() const;// only visible to Cup
    15 };
    16 
    17 template <typename T> void Box::doSomething(const T &obj, const Cup &c)
    18 {
    19     c.func();
    20 }
    21 
    22 #endif // BOX_H

    Box3.cpp

     1 #include "Box.h"
     2 
     3 #include <iostream>
     4 
     5 Box::Box()
     6 {
     7 
     8 }
     9 Box::~Box()
    10 {
    11 
    12 }
    13 
    14 void Box::func() const
    15 {
    16     using namespace std;
    17     cout << "Box.func" << endl;
    18 }

    main3.cpp

     1 #include "Box.h"
     2 #include "Cup.h"
     3 
     4 int main()
     5 {
     6     Cup c;
     7     Box b;
     8     c.doSomething<int>(1, b);
     9     b.doSomething<int>(1, c);
    10     return 0;
    11 }

    Cup3.h

     1 #ifndef CUP_H
     2 #define CUP_H
     3 
     4 class Box;
     5 
     6 class Cup
     7 {
     8     friend class Box;
     9     public:
    10         Cup();
    11         ~Cup();
    12         template <typename T> void doSomething(const T &obj, const Box &b);
    13     private:
    14         void func() const; // only visible to Box
    15 };
    16 
    17 template <typename T> void doSomething(const T &obj, const Box &b)
    18 {
    19     b.func();
    20 }
    21 
    22 #endif // CUP_H

    Cup3.cpp

     1 #include "Cup.h"
     2 
     3 #include "Box.h"
     4 
     5 #include <iostream>
     6 
     7 Cup::Cup()
     8 {
     9 
    10 }
    11 Cup::~Cup()
    12 {
    13 
    14 }
    15 
    16 void Cup::func() const
    17 {
    18     using namespace std;
    19     cout << "Cup.func" << endl;
    20 }
  • 相关阅读:
    kubernetes 集群YAML文件
    kubernetes 集群搭建 -- 二进制方式
    BetterIntelliJ IDEA失效的解决办法:This license BISACXYELK has been cancelled
    win10下迁移EFI分区表
    Java 8 Optional——避免空指针异常的小工具
    4个常见的IO模型——阻塞、非阻塞、多路复用、异步
    CountDownLatch笔记
    JAVA集合-03ArrayList源码解析和使用实例
    Secure Shell登录
    Kali(2020.4版本)遇到的metasploit启动崩溃问题
  • 原文地址:https://www.cnblogs.com/qrlozte/p/4113211.html
Copyright © 2011-2022 走看看