What The Struct

What’s the difference between a C++ struct and class? The difference is crazy so hold on to your underwear….

By default, structs have public member access and classes have private member access.

You can put your underwear back on now…

Both structs and classes can have these:

  • Inheritance
  • Private, public, and protected members
  • Member functions
  • Constructors
  • Operator overloading
  • Used as a template
  • Serialized to a file without extra garbage

If you already explicitly use access modifiers, then there is no difference.

Despite this, I have a reason for choosing one over the other. I use structs to represent plain old data. I’ll use public getter and setter methods on structs, but structs do not abstract any other functionality. Structs represent the data, not how to use the object.

Here is a struct for texture data in QGL:

struct TEXTURE_BUFFER
{
   std::vector<uint8_t> Data;
   std::vector<D3D12_SUBRESOURCE_DATA> Subresources;
   D3D12_RESOURCE_DIMENSION ResourceDimension;
   DXGI_FORMAT Format;
   UINT Width;
   UINT Height;
   UINT Depth;
   UINT MipCount;
   UINT ArraySize;
   bool CubeMap;
};

I use classes when there is additional functionality. The vector class support operations like push_back and begin. A binary tree supports searching and adding nodes.
Here is a class the abstracts the texture buffer so it can be uploaded to the GPU, evicted from the GPU, and provide descriptions for the DirectX 12 pipeline.

class texture : public iresident<D3D12_RESOURCE_DESC, D3D12_SHADER_RESOURCE_VIEW_DESC, ID3D12Resource>
{
   public:
   using DescriptionT = D3D12_RESOURCE_DESC;
   using ViewDescriptionT = D3D12_SHADER_RESOURCE_VIEW_DESC;

   texture(const TEXTURE_BUFFER& textureData,
            const winrt::com_ptr<d3d_device>& dev_p);

   texture(TEXTURE_BUFFER&& textureData,
            const winrt::com_ptr<d3d_device>& dev_p);

   texture(const texture& r);

   texture(texture&& r);

   virtual ~texture();

   virtual DescriptionT description() const
   {
      return m_textureDesc;
   }

   virtual const DescriptionT* put_description() const
   {
      return &m_textureDesc;
   }

   virtual ViewDescriptionT view() const
   {
      return m_viewDesc;
   }

   virtual const ViewDescriptionT* put_view() const
   {
      return &m_viewDesc;
   }

   protected:
   friend class copy_command_list;
   virtual void p_upload_resources();

   private:
   DescriptionT m_textureDesc;
   ViewDescriptionT m_viewDesc;
   TEXTURE_BUFFER m_data;
};

Use whatever you want though. Regardless of your choice, you get the same functionality.