0

Say I have my own built class (I won't cite an example due to length) X, and in the protected section, has a class Y (from an external library I cannot modify, and cannot use inheritance from the class as the member definitions are hidden).

Class Y has about 40 functions. 20 of those I don't want the user to be able to access or modify as it would entail broken functionality (prevented by protected status in class X currently), but the other 20 functions I want the user to be able to access and thus modify class Y (almost as if they had direct access minus the so-called 'dangerous' functions).

Without writing out 20 functions in class X which are exact duplicates of class Y, is there any easier and faster way to grant the user access to the 20 or so functions (like some sort of function forwarding ability or something)?

Expanded note:

It's a bit tricky, because there's a library function that takes a class Y (but won't accept a class X, and people complain at me for casting between classes). Class X is supposed to automate and store information for class Y's operations, be able return a (const) class Y for the function, and allow the user to modify the simple things (such as position of the object) but not the automated things (images, image loop).

Class X being a type of class Y works in automated functions but doesn't allow class X to return a class Y (not being able to reference itself, a modified version of class Y, again, people will complain at me for casting between classes).

user1433767
  • 645
  • 2
  • 6
  • 14
  • If it where me, I would make Y public and make a nice documentation telling which functions they should and which they shouldn't use. But again, I'm more of a C programmer... – Shahbaz Aug 09 '12 at 09:52

1 Answers1

4

Why can't you inherit from class Y? If you can use it at all, you can inherit from it.

You can solve your problem using non-public inheritance (probably private inheritance) and then lifting the functions you want from Y via using declarations:

class Y
{
public:
  void FunctionIWantToExpose();
  void AnotherFunctionIWantToExpose();
  void FunctionIDontWantToExpose();
}

class X : private Y
{
public:
  using Y::FunctionIWantToExpose;
  using Y::AnotherFunctionIWantToExpose;
}

int main()
{
  X x;
  x.FunctionIWantToExpose(); // This is legal and calls Y::FunctionIWantToExpose()
  x.FunctionIDontWantToExpose(); // This will cause a compile error
  return 0;
}

EDIT: If you want to provide access to the internal Y object, you can do it easily with an additional member function in X:

const Y& GetY() const
{
  return *this;
}

This works inside class X because the base class Y is accessible there. A version of GetY() returning just a Y&, on the other hand, is completely unadvisable, since class clients could use it to modify your X objects using the Y methods you wanted to block.

Gorpik
  • 10,940
  • 4
  • 36
  • 56
  • If I wanted to return the class Y itself (const &Y GetY() const, for example), how would I do this with inheritance? – user1433767 Aug 09 '12 at 10:19
  • 1
    `const Y& GetY() const {return static_cast(*this);}` should do the trick, at least as long as `X` does not inherit from any other classes. – Gorpik Aug 09 '12 at 10:51
  • @j_random_hacker: I think `static_cast` will work here, but I am ready to stand corrected. I don't like this `GetY()` function either and don't feel too comfortable with these casts. – Gorpik Aug 09 '12 at 10:53
  • Doesn't inherit, but it utilises another class (call it Z if you want) to help automate and store information. I have a feeling that is going to interfere... – user1433767 Aug 09 '12 at 10:53
  • @Gorpik: It sticks out in my memory because back in http://stackoverflow.com/a/845076/47984 I made the same claim as you did and got bitten. But looking at 5.4/7 again in the C++03 standard, it implies that the conversion permitted by the C-style cast is also permitted by some combination of new-style casts involving `reinterpret_cast<>`... – j_random_hacker Aug 09 '12 at 11:19
  • ... which is troubling, since `reinterpret_cast<>` gives hardly any guarantees. E.g. if `C` inherits privately from both `A` and `B`, then when converting a `C*` to either `A*` or `B*`, at least one of those conversions "ought" to change the pointer value, but `reinterpret_cast<>` resolutely refuses to say whether it will change the pointer value at all; and indeed, you could also argue that it "ought" never to change the pointer value ("forget everything you know and reinterpret this pointer value as a pointer to such-and-such"). TL;DR: C++ is horrifying. – j_random_hacker Aug 09 '12 at 11:21
  • 1
    @j_random_hacker: I see, but I think this is true only outside class `X`. Inside it (for instance, in the implementation of `X::GetY()` you can actually do the `static_cast` and it will work. After all, inside `X`, `X` inherits from `Y`. – Gorpik Aug 09 '12 at 11:27
  • To be more precise: inside `X`, base class `Y` is accessible. You can even use `dynamic_cast` instead of `static_cast` in my `GetY()` implementation. – Gorpik Aug 09 '12 at 11:40
  • @Gorpik: You're absolutely right! This makes a lot of things that previously seemed arbitrary and confusing make sense. Thanks! But: I would suggest not using either `dynamic_cast<>` or `static_cast<>` -- the `GetY()` implementation actually needs no cast whatsoever as it's only converting a pointer-to-derived to a pointer-to-base! :) – j_random_hacker Aug 09 '12 at 12:17
  • 1
    @j_random_hacker: Oh, always overcomplicating things :) Indeed, no cast is always much better than any cast. I am updating my answer with the final version. – Gorpik Aug 09 '12 at 12:20
  • Deleted my first comment as it might have misled people who only read the 1st few comments... and not out of any sense of shame that Gorpik's sensible explanation eluded me all this time! Not at all! :) – j_random_hacker Aug 09 '12 at 12:36
  • @j_random_hacker: Comments are intended to clarify or improve answers, and yours helped improve mine, so thanks a lot for them. – Gorpik Aug 10 '12 at 06:44