0

My goal here was, instead of placing all methods in ServerInterface(superclass), i wanted to place the methods in child classes to organize the code better.

class ServerInterface
{
public:
    Router* router = new Router();
    Client* client = new Client();
    ServerInterface() {

    } //Creates new Router and Client instance
};

class Router : public ServerInterface
{
public:
    Router() {}
    void randomRouterFunction() {}
};

class Client : public ServerInterface
{
public:
    Client() {}
    virtual void randomClientFunction() {};
};



class ProductionServer : public ServerInterface
{
public:
    ProductionServer() {}
};

int main() {
    ProductionServer* productionServer = new ProductionServer();
    productionServer->router->randomRouterFunction(); //causes it to not debug
    return 0;
}

In my situation I am only allowed to access to ProductionServer which has to inherit from ServerInterface in my code. So instead of calling productionServer->randomRouterFunction() or productionServer->randomClientFunction(), i wanted to be able to call productionServer->Router->randomRouterFunction() etc

Even though intellisense tells me that it's all working fine, trying to run my code i recieve

main:289:20: error: 'class ProductionServer' has no member named 'router'

productionServer->router->randomRouterFunction();

Is this even feasible to accomplish? The reason for thinking it may not work is cause the superclass creates a member of Router which is the child class, and then the router child class creates another superclass since it inherits it, which then creats another router child class in the superclass.... and it would be an infinite loop? XD

ps. The randomFunction() could be any method, just used as an example.

CoffeDev
  • 258
  • 2
  • 12
  • We can't actually see the broken code, CoffeDev... present your [mcve]. – Asteroids With Wings Nov 03 '20 at 20:40
  • Does this answer your question: [Resolve build errors due to circular dependency amongst classes](https://stackoverflow.com/questions/625799/resolve-build-errors-due-to-circular-dependency-amongst-classes) ? – πάντα ῥεῖ Nov 03 '20 at 20:40
  • _" the superclass creates a member of Router which is the child class"_ It does not; you have a `Router*`, not a `Router`. – Asteroids With Wings Nov 03 '20 at 20:40
  • @πάνταῥεῖ No, that would be more like `class ProductionServer undeclared`.... and there's no evidence of multiple headers here anyway, let alone circular dependencies. Let's not jump the gun, eh? – Asteroids With Wings Nov 03 '20 at 20:41
  • @AsteroidsWithWings oh sorry missed it, will edit :D – CoffeDev Nov 03 '20 at 20:41
  • Your code example is improving. Please add a `main()` method so that we can compile and run it ourselves without any modifications. – Code-Apprentice Nov 03 '20 at 20:44
  • *Can* you — yes (with some fixes). Does it make sense? Almost certainly no. Think about it: at the moment, both your `Router` and your `Client` class contain `Router` and `Client` members themselves. Is this meaningful? – Konrad Rudolph Nov 03 '20 at 20:44
  • Does it make sense for `Router` to subclass `ServerInterface`? Same for `Client`? A big part of OO is deciding the responsibility for each class. I think a `ProductionServer` that subclasses `ServerInterface` makes a lot of sense, but not `Router` or `Client`. – Code-Apprentice Nov 03 '20 at 20:45
  • will add runnable code :D It's actually such a big library that i just took some snippets for showcase, will edit in a second XD – CoffeDev Nov 03 '20 at 20:46
  • @Code-Apprentice I see how you mean, thats a very good point. In the beginning i had all the methods inside ServerInterface, and there was 100+ functions, so i wanted to find a way to organize the code more into groups so it could be like ServerInterface->Group1->anyFunctionInside(); – CoffeDev Nov 03 '20 at 20:50
  • @CoffeDev It sounds like your ServerInterface does need broken up. I think "groups" isn't the right way, though. Instead, look for several functions that support a similar purpose. Then instead of naming them `Group1`, `Group2`, etc. name them according to that mutal purpose. – Code-Apprentice Nov 03 '20 at 21:55
  • @CoffeDev To get you thinking about how to split up your ServerInterface class, I suggest you read about the Single Responsibility Principle. – Code-Apprentice Nov 03 '20 at 21:56

1 Answers1

1

The problem is with the design. You can compile this but when you create a ProductionServer it will instantiate a ServerInterface which will create a Router and a Client and those will both also instantiate a ServerInterface that will create a Router and a Client and so on - until you get a stack overflow.

In order to get this in some working condition, you need to add something that breaks that cycle so that it doesn't instantiate Routers and Clients endlessly.

Ted Lyngmo
  • 93,841
  • 5
  • 60
  • 108
  • Oh that was what i was afraid of :( Is there any other way to group in a similar fashion, witthout having to place all methods in the ServerInterface? – CoffeDev Nov 03 '20 at 20:55
  • 1
    @CoffeDev There are always options but it'll be easier to advice with some real world functions. One option is [CRTP](https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern) but then you loose some other advatages. – Ted Lyngmo Nov 03 '20 at 20:57
  • I can confirm by the way, the reason for it not compiling was the exact reason you mentioned! The way i made it work was to name ServerInterface to SuperServerInterface, and have a child class that is named ServerInterface which instead creates the router and client, so no infinite loops and voila it worked. Thanks for your help! – CoffeDev Nov 03 '20 at 21:04
  • @CoffeDev You are welcome, but I actually _did_ compile it successfully (with added forward declarations for `Router` and `Client`). It fails in run-time due to stack overflow. I may have grabbed one of your earlier edits of the code. I turned the raw pointers into smart pointers like [this](https://godbolt.org/z/G5sTqW) and noticed that it exited badly and spotted the endless creation cycle. – Ted Lyngmo Nov 03 '20 at 21:08
  • i did something similar to this https://godbolt.org/z/xo3s4z, to avoid endless loops. The library i am using in my microcontroller is so huge and a mess that it's hard to make a good showcase for it XD – CoffeDev Nov 03 '20 at 21:33
  • 1
    @CoffeDev Why does `ServerInterface` have a `Client`? Usually the server and client are two wholly separate things. I think you need to continue thinking about how you separate things out in your classes and just as importantly how the classes related. Also, I strongly suggest finding a better name than `SuperServerInterface`. Names should describe what their purpose is and the prefix "Super" adds no meaning to the purpose of this interface. – Code-Apprentice Nov 04 '20 at 02:54