0

I'm currently having issues with dynamic_cast<> and how I've structured my code. So I have the Manager class, which gets a pointer and attempts to check if its a Derived object, and if it is, run some additional codes in the if statement. But in order for the dynamic_cast<> to work, it requires the class definition to come before the actual dynamic_cast<> usage.

So I've swapped the location of the class Manager and class Derived definition, to make the Derived class's definition to come earlier than the Manager class. But now, I'm having error messages saying that "Manager" is an undefined type. I'm guessing in order to pass Manager as a reference, the Derived class requires Manager's class definition to be defined first.

My best solution that I can think of is instead of passing the Manager class as a reference, pass it down as a pointer (which I am not quite a fan of since I know Manager class will always be a valid pointer so its pointless to make it a pointer). I was just wondering if there are any alternative and better solution than the one I have.

Thank you very much in advance!

Edit: I unfortunately need all of the class definition and implementations to be on one file, so splitting them into .h and .cpp file is a less ideal. For people asking, yes, it is homework, but my professor wants it in one file.

class BaseClass
{
    virtual VirtualClassName() = 0;
};

class Manager
{
    void FunctionNameOne(const BaseClass* const ClassPointer)
    {
        if(Derived* DerviedPtr = dynamic_cast<Derived*>(ClassPointer))
        {
            //Do stuff with DerviedPtr
        }
    }   
};

class Derived : public BaseClass
{
    Void FunctionNameTwo(const Manager& Manager)
    {
        //Do stuff with Manager
    }
};
JamesL
  • 11
  • 4
  • related/dupe: https://stackoverflow.com/questions/625799/resolve-build-errors-due-to-circular-dependency-amongst-classes – NathanOliver Feb 01 '19 at 16:28
  • 1
    First of all you need semicolons after your class definitions. – Paul Belanger Feb 01 '19 at 16:28
  • 1
    It is common practice to have variables start with a lower case character (or with an underscore + lowercase in the case of member variables). It gets really hard to tell if you mean the type `Manager` or the instance (well, const reference) `const Manager& Manager` otherwise. – Max Langhof Feb 01 '19 at 16:43
  • Are you familiar with the concept of a "forward declaration"? It might be just what you need. – Tim Randall Feb 01 '19 at 16:45
  • @TimRandall Forward declaration does not work in this case. – JamesL Feb 01 '19 at 16:49
  • 1
    Your problem really stems from the desire to use `dynamic_cast`. Fix *that*; restructure your code so that you don't need it. Why does `Manager::FunctionNameOne` need to know about `Derived`, even though it takes `BaseClass` as the type? – Nicol Bolas Feb 01 '19 at 16:57

2 Answers2

2

Usually, you put declarations into the .h files of your project and the implementations of the methods into the .cpp files.

If you follow this way, all class definitions are known and you can, without issues, use dynamic cast in this case.

IceFire
  • 4,016
  • 2
  • 31
  • 51
  • I've editted my question, what would be a good way if splitting them into .h and .cpp file is not ideal? – JamesL Feb 01 '19 at 16:34
  • 1
    @JamesL You can still move the method definitions to the bottom of the same file – IceFire Feb 01 '19 at 16:36
  • Oh! I see what you mean! Thank you very much, I think that'll be better than having one function take a pointer. – JamesL Feb 01 '19 at 16:39
  • Note that you will probably still need forward declarations to write out the function declarations at the top. – Max Langhof Feb 01 '19 at 16:45
0

I had to clean up the code, you should at least have well formed code to work with or your error messages will be meaningless.

class BaseClass
{
    virtual void VirtualClassName() = 0;
};

class Manager
{
    void FunctionNameOne(const BaseClass* const ClassPointer);
};

class Derived : public BaseClass
{
    void FunctionNameTwo(const Manager& Manager)
    {
        //Do stuff with Manager
    }
};

void Manager::FunctionNameOne(const BaseClass*  ClassPointer)
{
    if (const Derived* DerviedPtr = dynamic_cast<const Derived*>(ClassPointer))
    {
        //Do stuff with DerviedPtr
    }
}

Notice that I define FunctionNameOne and use of dynamic cast after the declaration of Derived.

lakeweb
  • 1,859
  • 2
  • 16
  • 21
  • Sorry, I'l keep that in mind for future posts. I guess having one of them take a pointer would be my best shot. – JamesL Feb 01 '19 at 16:36