daymick 0 Newbie Poster

Hello,

I would like to apply object-orientated programming in C++ to sets of 3D images. I would like to do 4 classes:
-dataset:an array of 3D images, contain the nb of 3Dimages as an object
-3Dimage:an array of 2D images, contain the nb of 2D images as an object
-2Dimage:an array of voxels, contain the nb of voxels as an object
-voxel

The main issue I am concerned with is:
-how to organize these classes knowing each is included in the other one?
-which class should contain an instance of the other one?

As a simple implementation, knowing that the nb of 2D images per 3D image is the same in the set (and idem for the nb of voxels per 2D image):
-how can I get the total number of voxels of the dataset?

Should I do something like:
Nb_2Dimages=3Dimage[0]:Get_Nb_images();
Nb_voxels_2Dimage=3Dimage[0][0]:Get_Nb_voxels();
Number_of_voxels=Nb_2Dimages*Nb_voxels_2Dimage;

Many thanks for your help.

Michael

Dani AI

Generated

A few practical design notes that build on 's idea.

Prefer composition with standard containers: let Dataset own a vector of 3DImage, each 3DImage own a vector of 2DImage, and each 2DImage own a vector of Voxel (or use a flat vector for a 2D/3D layout). This keeps ownership clear and makes memory lifetime simple. Use size_t for counts and vector::size() for sizes (see the std::vector reference for behavior and complexity guarantees: std::vector - cppreference.com).

Two practical patterns:

  • If every 3D image has identical dimensions, store dims once in Dataset or in a shared shape object and compute totals as a product of dimensions. This is fast but requires ensuring the invariant stays true.
  • If sizes can vary, implement a totalVoxels() that walks the containers and sums sizes. That is robust and handles irregular data safely.

Performance and safety tips:

  • For large volumes consider a flattened contiguous buffer (single vector) per 3D image to improve cache locality and simplify indexing (provide x,y,z -> linear index helpers).
  • Avoid storing redundant counts you must keep in sync; compute from vector::size() or update in centralized setters.
  • Watch for overflow when multiplying dimensions; validate using 64-bit types or checks before allocation.
  • Use reserve() when constructing large containers to avoid repeated reallocations.

These choices cover common trade-offs between simplicity, correctness, and performance; pick the one that best matches expected invariants and memory constraints.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.