PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Thursday, July 7, 2022

[FIXED] How can I create objects of a nested class inside the parent class but in another header file?

 July 07, 2022     c++, class, nested, object     No comments   

Issue

I have a class Dmx with a nested class touchSlider. So before I had these classes in my main.cpp file and just created an object array of touchSlider within the Dmx class and it worked properly.

How can I implement this here, with different header files? The compiler gives an error message: invalid use of incomplete type 'class Dmx::touchSlider'

The object array is: touchSlider slider[10] = {50,130,210,290,370,50,130,210,290,370};

dmx.h

// dmx.h

#ifndef dmx_h
#define dmx_h

class Dmx {
  public:
    byte number;                                                

    Dmx(byte numberA) {                                                 
      number = numberA;
    }

    void settingsDisplay();
    
    class touchSlider;             // declaration of nested class

    touchSlider slider[10] = {50,130,210,290,370,50,130,210,290,370};  
};

#endif

touchSlider.h

// touchSlider.h

#ifndef touchSlider_h
#define touchSlider_h

#include "dmx.h"

class Dmx::touchSlider{
  private:
  int pos;                                     

  public:
  touchSlider(int posA){                        
    pos = posA;                      
  }

  void printChannel();

};

#endif

main.cpp

// main.cpp

#include "dmx.h"                
#include "touchSlider.h"

Dmx dmx[10] = {Dmx(1), Dmx(2),Dmx(3), Dmx(4), Dmx(5), Dmx(6), Dmx(7), Dmx(8), Dmx(9), Dmx(10)}; 


void Dmx::settingsDisplay() {
    // do something
}

void Dmx::touchSlider::printChannel() {
    // do something
}

My previous code (that worked great) where both classes where in the same file looked like this:

class Dmx {
  public:
    byte number;                                                

    Dmx(byte numberA) {                                                 
      number = numberA;
    }

    void channelDisplay(){
    }                                            

    void settingsDisplay(){
    }
    
    class touchSlider{
    private:
      int pos;                                     

    public:
      touchSlider(int posA){                        
         pos = posA;                      
      }

      void setChannel(/* some arguments*/){
      }

      void printChannel();
      }
   };             

    touchSlider slider[10] = {50,130,210,290,370,50,130,210,290,370};        
};
Dmx dmx[10] = {Dmx(1), Dmx(2),Dmx(3), Dmx(4), Dmx(5), Dmx(6), Dmx(7), Dmx(8), Dmx(9), Dmx(10)}; 

Solution

To be able to create an array:

touchSlider slider[10] = {50,130,210,290,370,50,130,210,290,370};

You need the class definition available, because the compiler needs to know

  1. the size of the struct or class in use and
  2. if there's a suitable constructor available.

You now have two options, either you provide the class definition in the header but implement the class within the source file like:

// header:

class Dmx
{
public:
    // ...

    class TouchSlider
    {
    public:
        // only DECLARE here:
        TouchSlider(int posA);
        void setChannel(/* some arguments*/);
        void printChannel();
    };
};

// source:

Dmx::TouchSlider::TouchSlider(int posA)
    : pos(posA) // note: prefer the initialiser list!
{ }

void Dmx::TouchSlider::setChannel(/* some arguments*/)
{
}

// ...

or you hide away the implementation as you intended, but then you need to allocate the memory dynamically (this is the PImpl idiom) – at best with help of a std::unique_ptr:

class Dmx
{
public:
    // ...
private:
    class TouchSlider; // just declare

    std::unique_ptr<TouchSlider[]> sliders;
};

Important (see cppreference), though:

std::unique_ptr may be constructed for an incomplete type T, such as to facilitate the use as a handle in the pImpl idiom. If the default deleter is used, T must be complete at the point in code where the deleter is invoked, which happens in the destructor, move assignment operator, and reset member function of std::unique_ptr.

I.e. you cannot implement e.g. your class' destructor in the header file either but need to do so in the source file as well – after the nested class' full definition – alike any function that might re-assign another array.

The std::unique_ptr avoids necessity of manual memory management (see rules of three/five), on the other hand the class gets non-copiable (but you can work around by providing your own custom copy constructor and assignment while defaulting the move constructor and assignment).



Answered By - Aconcagua
Answer Checked By - Clifford M. (PHPFixing Volunteer)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing