Access Derived Class When Only Base Class Header is Included - c++

I'm trying to understand if there is a way set an include directive for a base class but also be able to access derived classes that are defined in a different header than the base class. For instance:
In GenericObject.h:
class GenericObject {
/* whatever - shared properties and methods implemented in .cpp file */
}
In Ball.h:
class Ball : public GenericObject {
/* whatever - implementation details are in the .cpp file */
}
Now in some other implementation file (let's call it the main.cpp), I have #included "GenericObject.h". In main.cpp, I want to be able to access both the members of the GenericObject class as well as the Ball class and any other derived class of GenericObject. From my trials so far, the compiler won't recognize the Ball identifier if I try to declare it like Ball * b; and thus any of the members that belong to its class.
Is this because my #include'd "GenericObject.h" file is not also linking that there is this derived Ball class for me to access? I can correctly ID and use the Ball class if I "#include "Ball.h" but I can't imagine I should include all of the header files of derived classes of the GenericObject class, right?
If I had to take a guess at how this might work, I'd guess that something like a prototype declaration for the Ball class inside the GenericObject class would be a step in the right direction but I'm not sure if a class prototype is even a thing.
Thanks for reading and any feedback everyone!

No, you can't use any identifier that's not yet described. This includes any class, whether it derives from a base or not.
It seems to me you are violating Liskov. If you receive a reference or pointer to a base then you should not be doing anything that requires you know that there is a derived or not. You should only be using the interface of the base. Thereby you no longer need to include the headers for derived classes where you're not using something defined only in THEIR interface.

I can't imagine I should include all of the header files of derived classes of the GenericObject class, right?
If you want to access any class derived from GenericObject, other than through a pointer or a reference, you will need to #include the header file for them.
If you can get by with using just pointers and references, you don't need to #include the header files but you still have to forward declare them.

Related

C++ helper functions in class, how to use them?

In my class in C++ I want to write a helper function (Which external users can't see or use) and found 2 ways to do that:
1) To declare it as private in the .h file and write the implementation in .cpp file.
2) To write the implementation directly in .cpp file without declaring it in the .h file.
What's the correct way, the difference or the advantage one have on the other?
Since you are not exposing this function through your interface, you should not declare it in the public header file. If you use it in a single cpp file, declare it in an anonymous namespace in that cpp file. If you use this function in multiple cpp files but you would still like to not make it a part of your interface, you can create internal header files that you #include in your source files, but aren't a part of your library's public interface.
The way is to create a class A that would be visible to the public, then create a descendant class B of this class and implement it privately. Then, when you are asked to create an A*, create a B* which is also an A* and return it. Your code sees a B* but the user of the class sees A* and may only access methods and variables declared in A. You also need to create/destroy your pointers with some function rather than with new/delete.
Pretty much like how COM implements IUnknown and stuff.

Inheritance and Includes

Lets say I have 2 classes. One is BaseClass and one is DerivedClass, being a derived class of BaseClass. I need to be able to create objects of both classes in another file. By using an #include statement to include the derived class in the new file, I have access to the derived class directly and the base class indirectly (as the derived class includes it in its file). Is it better to use this method of indirect "access" to the base class, or would it be better to directly include it alongside the derived class in the file?
The general advice is include what you use.
If you are coding to an API specification, and that specification does not explicitly detail the base-derived nature of the classes, then any changes to that relationship may break the includes that the files you depend on use.
See here as well.
If you are certain the BaseClass will always the base to the DerivedClass, then there may be little need include both, but for clarity, I would go ahead and do it anyway, it shows your intent.
Including all needed headers instead of relying on transitivity gives has two advantages:
If your header files will be refactored, you will not need to change your cpp file.
It clearly identifies your intent for other developers.

If i include a base class in a different class, will that base's derived classes be included also

If i include a base class in a different class, will that base's derived classes be included also. If i include lets say a shape class, and that class is a base class for the derived classes square and circle, will square and circle be included in that different class.
I want to do this, so if i decide to add another shape class later on(call it diamond), it will be easier writing...
#include <shapes.h>
rather than...
#include <square.h>
#include <circle.h>
#include <triangle.h>
No, it won't.
When you do #include<a.h>, the preprocessor recursively inline the content in a.h here.
So in your case you will only get the base class.
Besides, it is not a good idea to do this(include .h where base class is in and get all derived classes).
If you do that, maybe one day you only want to create a class derived from the base, you include all derived classes which are not used at all, increasing the code size.
No, the header files for the derived classes will not be included automatically. However, the good news is that in most cases you probably won't need to include the header files for the derived classes at all - the code responsible for creating the different shape objects needs to know about circles and triangles, but in most cases the code that (for example) draws the shapes can simply call a virtual draw function that will do the right thing for whichever kind of shape it happens to be given. Virtual functions are implemented in such a way that calling shape's draw function will correctly call the overridden versions for circle and triangle even if the header files for those classes aren't included in the file where the call is made.
If you find that your code regularly needs to know if something is a circle or a triangle (and hence needs to include the header files), that probably points to a problem with the shape class' interface. In that case, you should take another look at shape and see if you can change it in a way that you can call virtual functions and let the compiler sort out which is the correct implementation for each shape.
For the more general problem of having a whole bunch of header files that you often want to include together, you can make life easier by creating a single header file that includes all of the others. For example, you might create shape_library.h and put #includes for all of the different shape headers in there. That way, everything else can just include shape_library.h, and you only have one place to change if the headers get rearranged.

C++ Does an abstract class without any data fields need a constructor?

Does an abstract class without any data fields need a constructor?
Also, since the implementation of the makeAMove function is in the derived classes, is it necessary to create a separate implementation file for this Player class or is a this single .h file alright?
#pragma once // include guard
#include "Board.h"
class Player
{
public:
virtual void makeAMove(Board &myBoard) = 0; // pure virtual function
};
Every class has a constructor, probably more than one. However, you don't always need to declare or define a constructor yourself, since under favourable conditions this happens implicitly. Such is the case in your example.
You also don't need an implementation file, since that would not contain anything.
Yes, if the purpose of the abstract class is to provide polymorphic functionality through virtual funcions, that is, the class is an interface.
The base class should have a virtual dtor to ensure the correct destruction of polymorphic instances.
A good rule is: Every time a class hierarchy is dessigned to provide polymorphic functionality through dynamic binding, its base class should have a virtual dtor.
About classes and headers, C++ does not restrict you to write one class per file (as Java does).
What is more correct, to write one class per file or more than one classes? Depends, I think this is subjective. But in general C and C++ uses headers to provide functionality, and functionality commonly implies more than one class.

Why does compiler complain when I try to convert to a base-class?

BaseClass.h
class BaseClass
{
...
};
SubClass.h
#include "BaseClass.h"
class SubClass : public BaseClass
{
...
};
MyApp.h
class BaseClass;
class SubClass;
class MyApp
{
SubClass *pObject;
BaseClass *getObject()
{
return pObject;
}
};
I get a compiler error: error C2440: 'return' : cannot convert from 'SubClass *' to 'BaseClass *'
Why doesn't it work, surely you can automatically convert to a base-class without any casting?
Only post code which you have tested to exhibit the described behaviour.
Your code, with the "pOject" typo and the "..." parts removed, compiles just fine.
Edit after OP completely reworked the question:
The code in MyApp.h doesn't know that SubClass is a subclass of BaseClass, because you did not include the headers. All MyApp.h sees are forward declarations of the classes, which allows to handle pointers but doesn't allow to cast.
In "MyApp.h", you only have forward declarations of the classes, so it's not known that one derives from the other. You will need to include the "SubClass.h" before the body of getObject(); either include it from "MyApp.h", or move the body of getObject() into a source file and include it from there.
SubClass is not a BaseClass subclass in your example.
Apart from that your example compiles properly in my g++.
With the last edit you have, you are forward declaring 2 classes, and the compiler will not know that one is subclass of the other that way so no conversion is available.
MyApp.h doesn't tell the compiler that SubClass inherits from BaseClass - you should probably include baseclass.h and subclass.h in your myapp.h file as long as you have getObject() inlined there.
Edit: In your MyApp.h you should #include "SubClass.h". The forward declaration alone that you have has no info about one being a subclass of the other.
About your first post's problem: (Trying to store a BaseClass inside a SubClass)
You have had it mixed up. (Your edit fixes the problem)
A BaseClass pointer or reference can hold a SubClass memory address. Not the other way around.
A subclass is a base class and that's why all of a base class's methods and properties will apply to it.
If you had it the other way, you could store a base class address in a subclass pointer or reference, then that's a problem because you can call some method that a base class object doesn't support.
Because your classes are forward declared, therefore while parsing your header file the compiler has no idea that the two types are related.
You should move this method to the source file MyApp.cpp in which you will include SubClass.h.
The code works for me on g++ -pedantic (after changing pOject to pObject). The error must be somewhere else.
Your updated code contains the error:
class BaseClass;
class SubClass;
How is the compiler to know that these two classes are related? From the compiler’s point of view, the classes have no relationship whatsoever, so they cannot be interchanged.
Remove the forward declarations and instead #include "SubClass.h" to make the code work.