You are here:

C++/Classes & Members

Advertisement


Question
Is there a way to have one class include another class?

Say you have class_A, class_B and class_C, and you have data_class_A, data_class_B and data_class_C.

You want class_A to have data_class_B and data_class_C.
You want class_B to have data_class_A and data_class_C.
You want class_C to only have data_class_B.

I looked and friends and child classes but not sure that would achieve what I'm after. Can it be done?

Answer
Almost certainly. It depends on what exactly you mean by the term "have one class include another" and "to have".

Assuming you mean can you have a class whose instances (i.e. objects) contain data parts that are instances (i.e. objects) of other classes then the answer is of course "yes":

   class class_A
   {
       data_class_B    bData_;
       data_class_C    cData_;

   // ...

   };

   class class_B
   {
       data_class_A    aData_;
       data_class_C    cData_;

   // ...

   };

   class class_C
   {
       data_class_B    bData_;

   // ...

   };

In these cases the containing classes (class_A, class_B, class_C) only have public access to members of the class type data members they contain (data_class_A, data_class_B and data_class_C). If you require more access first review your design to see why you would require such access as often such requirements are failures of the design, and if you still feel a valid case can be made make the containing class a friend of the contained class in question.

If the any of the classes class_A, class_B or class_C can be said to be variations that specialise the behaviour of any of the data classes (data_class_A, data_class_B and data_class_C) then they should be sub classes of that data class. For example if you can say that class_C is a data_class_B specialisation then publicly derive class_C from data_class_B:

   class class_C : public data_class_B
   {

   // ...

   };

In this case class_C will get public and protected access to its data_class_B part.

Note however that in general classes have to be designed to be base classes that are meant to be derived from so if the data classes are not designed to be so then they should almost certainly not be used as base classes.

Depending on what you are doing you may prefer to hold references to data class members as pointers to those class objects. This might be the case if any of the data class object members of class_A, class_B or class_C objects are associated with are only known at the time of object creation, or maybe can be added to changed during the lifetime of the object, for example:

   class class_C
   {
       data_class_B  *  bData_;

   // ...

   public:
       class_C( data_class_B & the_data )
       : bData_(&the_data)
       {
       }
       
       UpdateData( data_class_B & the_data )
       {
         bData_ = &the_data;
       }

   // ...

   };

In such cases it important to know who owns the associated object.

[note: ownership implies responsibility for deleting an object]

In the above case although I have stored the reference to the data_class_B by pointer I pass the reference by C++ reference to the constructor of class_C. This would indicate that the object referenced may not have been created on the heap using new and therefore requires no explicit deletion and so objects of class_C do not own their referenced data_class_B objects.

If we were expecting a dynamically created object reference then I would have specified the reference be passed to the class_C constructor by pointer as this is what we get from new. Whether passing such an object reference (pointer) also transfers ownership would need to be clear and well documented,

The other point to be aware of is whether class_C objects share the referenced data_class_B object. If they take ownership of the referenced data_class_B object then presumably the data_class_B referenced should only be destroyed (deleted) after or during the destruction of the last class_C object referring to the given data_class_B object. In such cases reference counted smart pointers are useful such as the TR1 addition to the standard library std::tr1::shared_ptr (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1745.pdf for more on the TR1 update to the C++ standard library).

[note: not many C++ implementations currently include the TR1 additions so we can use the Boost (http://www.boost.org/) smart pointers instead (http://www.boost.org/doc/libs/1_36_0/libs/smart_ptr/smart_ptr.htm), and their tr1 support (http://www.boost.org/doc/libs/1_36_0/doc/html/boost_tr1.html)].

So in summary: yes you can include objects of one class in the data portion of another class's instances (and even as 'class' data if they are specified as static), and you can, if appropriate, derive one class from one or more others. Exactly which solution is best for a specific situation depends on the requirements and design criteria in force at the time.

For more on C++ and inheritance and object oriented design I suggest you look at Scott Meyers "Effective C++", items 35 - 44 (in the second edition) for starters - in fact any serious C++ developer should read this book from cover to cover and keep it close for reference as it has many good guidelines.

Finally please note that the code shown here are only fragments used to demonstrate specific points made in the answer text. They are not intended to be complete and may contain errors and typos - if so then I apologise.

Hope this helps. If not or you require further clarification then please ask another (possibly follow up) question.  

C++

All Answers


Answers by Expert:


Ask Experts

Volunteer


Ralph McArdell

Expertise

I am a software developer with more than 15 years C++ experience and over 25 years experience developing a wide variety of applications for Windows NT/2000/XP, UNIX, Linux and other platforms. I can help with basic to advanced C++, C (although I do not write just-C much if at all these days so maybe ask in the C section about purely C matters), software development and many platform specific and system development problems.

Experience

My career started in the mid 1980s working as a batch process operator for the now defunct Inner London Education Authority, working on Prime mini computers. I then moved into the role of Programmer / Analyst, also on the Primes, then into technical support and finally into the micro computing section, using a variety of 16 and 8 bit machines. Following the demise of the ILEA I worked for a small company, now gone, called Hodos. I worked on a part task train simulator using C and the Intel DVI (Digital Video Interactive) - the hardware based predecessor to Indeo. Other projects included a CGI based train simulator (different goals to the first), and various other projects in C and Visual Basic (er, version 1 that is). When Hodos went into receivership I went freelance and finally managed to start working in C++. I initially had contracts working on train simulators (surprise) and multimedia - I worked on many of the Dorling Kindersley CD-ROM titles and wrote the screensaver games for the Wallace and Gromit Cracking Animator CD. My more recent contracts have been more traditionally IT based, working predominately in C++ on MS Windows NT, 2000. XP, Linux and UN*X. These projects have had wide ranging additional skill sets including system analysis and design, databases and SQL in various guises, C#, client server and remoting, cross porting applications between platforms and various client development processes. I have an interest in the development of the C++ core language and libraries and try to keep up with at least some of the papers on the ISO C++ Standard Committee site at http://www.open-std.org/jtc1/sc22/wg21/.

Education/Credentials

©2016 About.com. All rights reserved.