简体   繁体   中英

C++ replace base class in derived class

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?

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.

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.

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).

The two classes do not generally match each other in memory layout (eg 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 ). Eg:

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_ptr s 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.

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;
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM