问题
Consider:
class A
{
public:
A( int val ) : m_ValA( val ) {}
A( const A& rhs ) {}
int m_ValA;
};
class B : public A
{
public:
B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
int m_ValB;
};
int main()
{
A* b1 = new B( 1, 2 );
A* b2 = new A( *b1 ); // ERROR...but what if it could work?
return 0;
}
Would C++ be broken if "new A( b1 )" was able to resolve to creating a new B copy and returning an A?
Would this even be useful?
回答1:
Do you need this functionality, or is this just a thought experiment?
If you need to do this, the common idiom is to have a Clone
method:
class A
{
public:
A( int val ) : m_ValA( val ) {}
A( const A& rhs ) {}
virtual A *Clone () = 0;
int m_ValA;
};
class B : public A
{
public:
B( int val4A, int val4B ) : A( val4A ), m_ValB( val4B ) {}
B( const B& rhs ) : A( rhs ), m_ValB( rhs.m_ValB ) {}
A *Clone() { return new B(*this); }
int m_ValB;
};
int main()
{
A* b1 = new B( 1, 2 );
A* b2 = b1->Clone();
return 0;
}
回答2:
What you're really looking for is called a virtual copy constructor, and what eduffy posted is the standard way of doing it.
There are also clever ways of doing it with templates. (disclaimer: self-promotion)
回答3:
Just a small addition to the answer by eduffy: Instead of
class B : public A {
...
A *Clone() { return new B(*this); }
...
};
you can declare it like this:
class B : public A {
...
B *Clone() { return new B(*this); } // note: returning B *
...
};
It's still considered a valid overriding of the virtual A::Clone();
and is better if called directly through B *
回答4:
The expression
new A(*b1)
already has a meaning, supposing you had the appropriate overload.
If it was given a different meaning, you'd have to provide another way to get the other meaning. This is kind of pointless given that there is already a way to get the meaning you want:
new B(*b1)
And guess which is clearer to read.
回答5:
Yes. No.
There are a number of ways of implementing cloning (e.g. the more or less standard clone() method, parameterized variations of object factories, with or without configurable dependency injection) without changing the meaning of existing programs, or making it impossible to create instances of base classes when a derived class is known within a compilation unit.
Constructors and destructors are sufficiently complex to understand for beginners as is. Injecting even more complexity into them would be unwise.
回答6:
As pointed out above there are a number of ways of implementing this.
To answer your question if new A( *b1 )
returned an new instance of B then this would not work.
int main()
{
A* b1 = new B( 1, 2 );
A a( *b1 ); // What size would 'a' be if it was polymorphicly constructed?
return 0;
}
来源:https://stackoverflow.com/questions/1021626/c-could-polymorphic-copy-constructors-work