4

I believe I'm thinking about this "badly" (non-C++'y). Here's what I'm trying to do

class AA {
    public:
        AA(const char* name, unsigned short number);

        int Write(int x);
    ...
    }

class BB: public AA {
    public:
        BB(const char* name, unsigned short number, const char* other);
        BB(AA aaObj, const char* other);

        int Write(double y, int x) {
            /* do something */
            AA::Write(x)
            }
    ...
    }

On the second BB constructor I'd like to replace the base object of BB with aaObj. I don't want a copy, I want the actual base object to the be same (same reference).

Questions:

  1. Is this possible?
  2. Is this a bad idea?
  3. Is there a better pattern for this (factory producing objects with shared members?
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
Dweeberly
  • 4,668
  • 2
  • 22
  • 41
  • 3
    That can't be done, at least with the way you are thinking. When calling BB Constructor, you are already creating another object on another memory address, so, you can't make them overlap in memory. One way you could do it is to add a AA pointer as a Private member on BB, that way you coudl save aaObj. – Ricardo Alves Aug 09 '18 at 14:50
  • 3
    I think inheritance is the wrong solution to your original problem, whatever it is. Ask a question about that problem instead – that is, the problem you are trying to solve by sharing base objects – and you’ll probably get more useful answers than ”you can’t do that”. – molbdnilo Aug 09 '18 at 15:03
  • Important: Your `Write` method should be `virtual` in `AA`, otherwise you are not actually overriding it in `BB` (just hiding). – Max Langhof Aug 09 '18 at 15:23

5 Answers5

3

This is not possible. Think of class hierarchies like nesting dolls. The derived class is the one on the outside and each successive base class is a nested doll. Since the base classes are contained in the derived class you can't use another base class as base class for the derived object.

One thing you could do if you want multiple objects to share the same object is to use a std::shared_ptr member. With that each object can have a pointer to the same object.

NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • Your answer is incomplete. OP can not use shared pointer in current design - there is nothing to point to. – SergeyA Aug 09 '18 at 15:06
2

From the description of the problem, looks like you want composition and not inheritance. Especially so that your Write function is no-virtual (and overloading a non-virtual function only makes sense in CRTP design, and your class is not CRTP).

Than, if you switch to composition, you can use a (smart) pointer to the owning object, and replace it at will.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
0

Each derived instance has its own instance of any base class, you cannot get around this. To have the derived type reference the same base instance requires that you change it from a derived is-a relation to a member has-a (and the member would then need to be either a reference or pointer).

SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23
0

The two classes do not generally match each other in memory layout (e.g. you might have additional data members in BB). Additionally, since you are in the constructor you are already creating a new object.

You cannot downcast to BB unless you are sure AA was originally a BB class (or sub-class of BB). E.g.:

BB b;
AA * a = dynamic_cast<AA *> (&b);
/* use initialization code for AA on a */
/* Now you could do (though this example becomes a bit weird): */
BB *bb = dynamic_cast<BB *> (a);

Why do you want to avoid making a copy? Do you have a large data-members? In that case consider using a shared_ptr on the relevant class members and implement an assignment-operator. So that doing:

AA a;
/* ... */
BB b;
b = a;

or

BB b(a)

become only a matter of assigning the shared_ptrs and consequently very cheap.

In short answer to your questions:

  1. Not in its current form, possibly by way of down casting. But this is probably a bad design.

  2. Yes. Probably.

  3. If you have a lot of members like strings etc, consider: keeping a reference to AA, copying AA to BB (this is probably not a big cost), refactoring so that you can instantiate BB directly and rather send the upward casted to AA to your initialization routine.

In order to give more detailed advice, we need more code or information about the particular issues you are trying to optimize.

gauteh
  • 16,435
  • 4
  • 30
  • 34
  • You cannot cast from `AA` to `BB` if `BB` inherits from `AA` (unless you are actually dealing with a `BB` instance through an `AA` pointer/reference, which is not the case here). – Max Langhof Aug 09 '18 at 15:28
  • You are right - I got that part mixed up. You can static_cast downwards when there are no additional members, but as far as I can see this might be undefined behavior/implementation specific. – gauteh Aug 09 '18 at 18:04
-1

What I would do in that position would be something Like this:

class BB{
public:
    BB(AA& aaObj, const char* other)
    {
        basepointer = &aaobj;
    }

    int Write(double y, int x) {
        basepointer->Write(x);
    }


private:
    AA* basepointer;
};
Ricardo Alves
  • 1,071
  • 18
  • 36
  • Wouldn't that require that I then redefine all the members for each derived class to avoid using the "actual" base class? – Dweeberly Aug 09 '18 at 14:57
  • I didn't understand what you meant. Do you mean that you will create a class that will derive BB and would have to implement the same pattern? – Ricardo Alves Aug 09 '18 at 15:00
  • Assume that AA is a more complicated object with several virtual functions. In BB I would have to implement each of those AA functions so that they used the basepointer rather than the actual base (of BB). – Dweeberly Aug 09 '18 at 15:03
  • Since on my example you are not deriving from AA, that will not be needed. – Ricardo Alves Aug 09 '18 at 15:06
  • Taking a pointer to the reference and putting it in the class member is a straight road to hell. – SergeyA Aug 09 '18 at 15:07
  • @SergeyA Why do you say that? – Ricardo Alves Aug 09 '18 at 15:09