First, how do you write a swap that does not throw? Must all of your members be pointers? What about a std::string? |
You can have the members as reference or as pointers, which ever you prefer. By reference would, perhaps, be more C++ -like way.
1 2 3 4 5 6
|
void Swap(YourType &a, YourType &b) throw()
{
YourType Tmp = a;
a = b;
b = Tmp;
}
|
Or a more general template solution:
1 2 3 4 5 6 7
|
template <class T>
void Swap(T &a, T &b) throw()
{
T Tmp = a;
a = b;
b = Tmp;
}
|
Or a Swap with pointers. This also works for std::string, although std::string has a built-in swap()
1 2 3 4 5 6
|
void Swap(YourType *const a, YourType *const b) throw()
{
YourType Tmp = *a;
*a = *b;
*b = Tmp;
}
|
The keyword "throw" in the function declaration dictates that the Swap() cannot throw.
Second, if you have an abstract base class that happens to contain members, how do you get around not being able to create a copy of an abstract base class? |
You are not meant to make a copy of an abstract class object, since it can't be instantiated.
If you like, you can make a pure virtual Copy() function:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
struct Base
{
virtual ~Base();
virtual void Copy(Base const &) = 0;
std::string Data;
};
void Base::Copy(Base const &Rhs)
{
Data = Rhs.Data;
}
struct Derivee : public Base
{
virtual void Copy(Data const &) {} // This actually never gets called
virtual void Copy(Derivee const &);
std::string MoreData;
};
void Derivee::Copy(Derivee const &Rhs)
{
Base::Copy(Rhs);
MoreData = Rhs.MoreData;
}
|
As in the example, there can be an implementation for a pure virtual function, like Base::Copy() here. Because Base cannot be instantiated, it can't obviously be called directly by operator .* dereference.
But you can call it from deriving classes.
It's been a while since I've done anything like this, so I don't know if this is the recommended textbook approach. Somebody might want to correct me here.
EDIT: Fixed syntax