0

Here is the problem, I have a vector of pointers to an abstract base class filled with derived objects like so:

class AbstractBase { /* ... */ };  

clase Derived1 : public AbstractBase {
    Derived1() { }
    Derived1( const AbstractBase& abc ) { /* ... */ }
};

/* ... */

vector< AbstratcBase* > lThingies;

const AbstractBase& getThingie(int pos) {
    return *lThingies[pos];
}

And to get copies of the elements I use the derived class "copy constructor" like so:

Derived1 d1 = getThingie(2);

But the problem is that I don't like this: There is no way to force the implementation of this "copy constructor" when building the class "derived42" and even when you do remember it's very easy to get it wrong (like making it a recursive call, happened to me).

My question is: Is there a better way to do this? how?

Update:
One of the "unwritten" requirements of the solution that I'm looking for is to get a copy of the derived object as a local variable, so I don't forget to delete it.

More info:
There are a number of lThingies and, at runtime, I can tell what are the derived objects contained within (derived1, derived2, etc.), but not at compile time.

4

3 回答 3

4

You could make a pure virtual clone function in AbstractBase which returns an AbstractBase pointer, and override clone in your derived classes.


STRICTLY OPINION:

This is sort of a gross and outdated practice though (in my opinion). I suggest re-architecting to eliminate the need to do this in the first place.

To elaborate on my 'gross and outdated' opinion of the virtual constructor idiom (I'm sure this will be controversial):

  • To actually be robust/generic clone would need to be templated for an allocator, like some STL constructs are. But, it can't be.
  • When do you actually want to copy an object of which you don't know the concrete type? I question the legitimacy of that use case.
于 2013-01-17T16:07:03.617 回答
0

Do you know your getThingie returns a Derived1? If you know this, possibly you should change the return type of Derived1 and the storage in the std::vector to be Derived1 instead of AbstractBase.

Assuming the above doesn't work, you can do a Derived1 bob = dynamic_cast<Derived1&>(getThingie(...));, which does a run-time check that the thingy is a Derived1 or more derived instance, and if so it does the cast -- if not, it throws an exception.

If you don't want to bother with the run time check because you are so certain that it is a Derived1, simply use Derived1 bob = static_cast<Derived1&>(getThingy(...));.

However, working with actual instances of classes which have an inheritance hierarchy is very questionable. There are many, many things that can go wrong.

于 2013-01-17T16:29:16.943 回答
0
class A
{
   public:
   virtual void toto() { std::cout << "Love Java" <<std::endl; }
   virtual A&& Duplicate() { return std::move(A()); }
};

class B : public A
{
   public:
   virtual void toto() { std::cout << "Love C++11" <<std::endl; }
   virtual B&& Duplicate() { return std::move(B()); }
};

int main()
{
   A *a = new B();;

   A&& b(a->Duplicate());

   a->toto();
   b.toto();
}

In the main you create a B on stack without know his type. (with rvalue reference in c++11)

于 2014-02-14T22:46:51.087 回答