Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ Polymorphism and Derived Class Types - "ugly programming" with pointer type casts

First up, I'm not sure exactly how to describe what I'm doing in one line... hence the slightly vague title.

The shortest description of the problem I can give is that "I have a function, and it should be able to take as an argument any of the many possible types of class, and these classes are all derived from a base class".

Specifically, I have 2 categories of class and both implement different types of method, which are similar but not exactly the same.

Perhaps it is better if I just give the example? You will see I do some slightly weird things with pointer type-casts. I don't think these are good programming practices. They are slightly strange at least, and I am wondering if there is an alternative, better method of doing things.

Okay so here goes my attempt at a simplified example:

class device
{
    // Nothing here - abstract base class
}

class inputDevice : device // inherit publicly, but it doesn't matter
{
    virtual input* getInput() { return m_input; } // input is a class
}

class outputDevice : device
{
    virtual output* getOutput() { return m_output; } // output is also a class
}

class inputoutputDevice : public inputDevice, public outputDevice
{
    // Inherits the get methods from input and output types
}

// elsewhere in program
void do_something(device* dev, int mode_flag)
{
    if(mode_flag == 1) // just an example
    {
        input* = ((inputDevice*)dev)->getInput(); // doing strange things with pointers
    }
    else if(mode_flag == 2)
    {
        output* = ((outputDevice*)dev)->getOutput(); // strange things with pointers
    }
    else if(mode_flag == 3)
    {

    }
}

So you see that the subtly here is that the function has some behavior dependent on whether we are dealing with an argument which is an input device or an output device.

I guess I could overload the function many times, but there could be many different types of input, output or both input and output devices... so that would be a rather convoluted method.

Putting the "get" methods into the base class doesn't seem like a good idea either, because the derived classes should NOT have the getInput() method if the device is an OUTPUT device. And similarly, and INPUT device should not have a getOutput() method. Conceptually that just doesn't seem right.

I hope that I explained that clearly enough and didn't make any mistakes.

like image 467
FreelanceConsultant Avatar asked Sep 27 '22 05:09

FreelanceConsultant


1 Answers

To expand on my comment, if you look at e.g. this input/output library reference you will see a class diagram that in a way reminds much of your class hierarchy: There's a base-class (two actually), an "input" class, and "output" class, and an "input/output" class that inherits from both the "input" and "output" class.

However, you never really directly references the base classes std::basic_ios or std::ios_base, instead once only uses references to std::ostream for any output stream, and std::istream for any input streams (and std::iostream for any input and output stream).

For example, to overload the input operator >> your function takes a reference to a std::istream object:

std::istream& operator>>(std::istream& input_stream, some_type& dest);

Even for more generic functions you take a reference to either an std::istream, an std::ostream or an std::iostreamobject. You never use the base class std::basic_ios just because of the problems you have.


To relate more to your problem and how to solve it, use two function overloads, one for the input device, and one for the output device. It makes more sense because first of all you wont have the problem with checking type and casting, and also because the two functions will operate quite differently depending on if you are doing input or output anyway, and trying to mix it both into a single function just makes the code much more unmaintainable.

So you should instead have e.g.

void do_something(inputDevice& device);

and

void do_something(outputDevice& device);
like image 135
Some programmer dude Avatar answered Nov 15 '22 08:11

Some programmer dude