| 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