0

DISCLAIMER: CCNode class is part of the cocos2d-x framework, which i didn't desing.

Base class CCNode has a init method:

virtual bool init();

My derived class needs two arguments, so I declare a new init method:

virtual bool init(int, int);

I'd like to enforce the use of the new init(int a, int) instead of the original one. I know I have the option to call the new one with default parameters, but it doesn't feel right in the context.

I'm searching for a way to tell the user "Call init(int, int) instead" if anyone tries to call that one. I'd rather get that at compile time that at runtime.

I've tried C++11's static_assert(false, "message"), but fails without calling it...

  • Your design looks flawed. What if you have a pointer to `CCNode` pointing to one of your derived objects? Should you still be able to call `init()`? What would it do? Should it dispatch to `init(int, int)`? Call it explicitly? The real question here is *what are you trying to accomplish?**. A better solution than this surely exists. – Luchian Grigore May 12 '13 at 16:49
  • possible duplicate of http://stackoverflow.com/questions/10727418/can-i-force-a-compiler-error-if-certain-functions-are-called – mwerschy May 12 '13 at 16:50
  • @mwerschy **not** a dupe (at least not of that). – Luchian Grigore May 12 '13 at 16:51
  • That question answers what is being asked here as far as I can tell. He's just trying to deprecate it or am I reading this wrong? – mwerschy May 12 '13 at 16:52
  • 1
    @mwerschy you're reading it wrong. Also, that question is about visual-C++ and free functions. – Luchian Grigore May 12 '13 at 16:53
  • @mwerschy I've read that. I'd like to get an error, a warning & a runtime error would suffice in case there isn't anything better... – Xavier Arias Botargues May 12 '13 at 16:54
  • Wouldn't making `init()` private work in your context? – Mat May 12 '13 at 16:54
  • @LuchianGrigore i've added a disclaimer, so you can see that only the second part of the design is mine. In any case i'd like to avoid users calling init while being able to subclass CCNode. – Xavier Arias Botargues May 12 '13 at 16:56
  • Can you pass the two `int`s as parameters to the constructor and keep the signature of init intact? – Luchian Grigore May 12 '13 at 16:57
  • @Mat no, as the user could cast down to CCNode – Xavier Arias Botargues May 12 '13 at 16:57
  • @XavierAriasBotargues as per your latest comment - why do you want to do that? The intention was to have `init()` overrideable with no parameters. – Luchian Grigore May 12 '13 at 16:58
  • @LuchianGrigore (Refering to your previous comment) that's an option, but then the information would be passed at construction and then the user could resend information (calling the new one) or call the old version, leaving the new version useless. I may end up doing this, as i want to be able to reinitialize the object. – Xavier Arias Botargues May 12 '13 at 17:01
  • @LuchianGrigore it's the framework convention to have all the information needed in the initialization passed to the init method, having multiple ways of initializing an object. – Xavier Arias Botargues May 12 '13 at 17:04
  • @XavierAriasBotargues do you have a link to some documentation? I tried searching but didn't find this init method. – Luchian Grigore May 12 '13 at 17:06
  • 2
    Oh, btw, a solution is to inherit `private`ly, but I still think the design is flawed. – Luchian Grigore May 12 '13 at 17:09
  • Framework's documentation: http://www.cocos2d-x.org/reference/native-cpp/index.html If i inherit privately i could manually expose the methods that i need. It's a good enough option. – Xavier Arias Botargues May 12 '13 at 17:09
  • I don't see any `init` in http://www.cocos2d-x.org/reference/native-cpp/d0/ded/classcocos2d_1_1_c_c_node.html#ad90caf1d040deb1ae1445311645e4d24 – Luchian Grigore May 12 '13 at 17:18
  • @LuchianGrigore init is not documented, but mentioned: "Subclassing a CCNode usually means (one/all) of: overriding init to initialize resources and schedule callbacks"... If you answer this question with the private inheritance solution i'll mark it as accepted :) – Xavier Arias Botargues May 12 '13 at 17:22
  • Is this really an issue then? Have you tried inheriting from CCNode and calling `init()`? Does it compile? – Luchian Grigore May 12 '13 at 17:31
  • @LuchianGrigore CCNode::init() only returns true. – Xavier Arias Botargues May 12 '13 at 17:33

2 Answers2

1

If your really want to prevent someone calling the standard node method I think you should inherit it privately. However, the more cocosy way of doing this would simply be to call the new init from your create method, which is the only one that should be called by outside code when constructing your object anyway.

Sebastian Ärleryd
  • 1,774
  • 14
  • 19
  • 1
    Your suggestion (if I get you right) to declare but not define the method will not do the trick. The code will (at least in MSVC12) not compile, even if the method is never called. The linker will try to resolve derived::init(void) upon creation of an instance of derived and exit in error. – Pixelchemist May 12 '13 at 18:35
0

Sounds like you have source code access, since you tried sticking a static assert in there? The only way I think you can do exactly what you want is to templatize the function in question. Placing a static assert in a templatize function is a good way to ensure it doesn't compile.

Another option would be to hide the declaration in the private section of your class.

Lastly, a run-time assertion is the most common way I ever achieve what you're asking to do.

If you don't have source code access to that init function, then I really don't think you can do what you're asking.

RandyGaul
  • 1,915
  • 14
  • 21
  • There's a lot of code (frameworks and mine) using that base class, so modifing it to include a template doesn't feel right – Xavier Arias Botargues May 12 '13 at 17:08
  • Yeah that's probably not a good option for a large framework, but it's the only way to do exactly what you've asked to do. Otherwise the function will always compile and fire off the static assert. – RandyGaul May 12 '13 at 17:09