面向对象的编程-位域私有结构的公共参考

时间:2019-04-05 23:09:49

标签: c++ c++11

在下面的代码中,我尝试从其父类(Building)访问类(Apartment)的私有字段(contamination_levels)。在这种情况下,我认为朋友函数无法提供帮助,因为我正在使用继承,但是如果我做错了,请更正我。

template<typename T>
struct Building {
    operator uint32_t() const {
        return (static_cast<T const *>(this)->contamination_levels);
    }
    void operator=(uint32_t const cl) {
        static_cast<T*>(this)->contamination_levels = cl;
    }
};


struct Apartment: Building<Apartment> {
    using Building<Apartment>::operator=;

public:
    Apartment(uint32_t const c = 0) : contamination_levels(c) {}

    uint32_t getAContLevel() {
        return roomA;
    }
    uint32_t getBContLevel() {
        return roomB;
    }
    uint32_t getCContLevel() {
        return roomC;
    }

private:
    union {
        struct
        {
            uint32_t roomA : 4;
            uint32_t : 4;
            uint32_t roomB : 4;
            uint32_t : 4;
            uint32_t roomC : 8;
            uint32_t : 8;
        };
        uint32_t contamination_levels;
    };
};


int main() {
    Apartment  Bayview2000 = 0x74352;
    uint32_t cont_level = Bayview2000;
}

main()的第2行运行时,它将调用在Building类中定义的强制转换运算符uint32_t()。从建筑物访问专用字段污染级别时会出现问题。

在所有字段都公开之前,处理私有字段不是问题。

1 个答案:

答案 0 :(得分:2)

为什么不尝试朋友?有用。测试它,您将看到它。

template<typename T>
struct Building
{
   operator uint32_t() const
   {
      return ( static_cast<T const *>( this )->contamination_levels );
   }
   void operator=( uint32_t const cl )
   {
      static_cast<T*>( this )->contamination_levels = cl;
   }
};


struct Apartment : Building<Apartment>
{
   // friend works.
   template<typename T> friend struct Building;

   using Building<Apartment>::operator=;

public:
   Apartment( uint32_t const c = 0 ) : contamination_levels( c )
   {
   }

   uint32_t getAContLevel()
   {
      return roomA;
   }
   uint32_t getBContLevel()
   {
      return roomB;
   }
   uint32_t getCContLevel()
   {
      return roomC;
   }

private:
   union
   {
      struct
      {
         uint32_t roomA : 4;
         uint32_t : 4;
                    uint32_t roomB : 4;
                    uint32_t : 4;
                               uint32_t roomC : 8;
                               uint32_t : 8;
      };
      uint32_t contamination_levels;
   };
};


int main()
{
   Apartment  Bayview2000 = 0x74352;
   uint32_t cont_level = Bayview2000;

   return 0;
}

但是更好的方法是使用公共的get和set函数(如果适合的话)(如果您不想隐藏这些功能):

template<typename T>
struct Building
{
   operator uint32_t() const
   {
      return ( static_cast<T const *>( this )->getContaminationLevels() );
   }
   void operator=( uint32_t const cl )
   {
      static_cast<T*>( this )->setContaminationLevels( cl );
   }
};


struct Apartment : Building<Apartment>
{
   using Building<Apartment>::operator=;

public:
   Apartment( uint32_t const c = 0 ) : contamination_levels( c )
   {
   }

   uint32_t getAContLevel()
   {
      return roomA;
   }
   uint32_t getBContLevel()
   {
      return roomB;
   }
   uint32_t getCContLevel()
   {
      return roomC;
   }

   uint32_t getContaminationLevels() const
   {
      return contamination_levels;
   }

   uint32_t setContaminationLevels( uint32_t cl )
   {
      contamination_levels = cl;
   }

private:
   union
   {
      struct
      {
         uint32_t roomA : 4;
         uint32_t : 4;
                    uint32_t roomB : 4;
                    uint32_t : 4;
                               uint32_t roomC : 8;
                               uint32_t : 8;
      };
      uint32_t contamination_levels;
   };
};


int main()
{
   Apartment  Bayview2000 = 0x74352;
   uint32_t cont_level = Bayview2000;

   return 0;
}