Books
in black and white
Main menu
Share a book About us Home
Books
Biology Business Chemistry Computers Culture Economics Fiction Games Guide History Management Mathematical Medicine Mental Fitnes Physics Psychology Scince Sport Technics
Ads

Symbian os Expleined effective C++ programming for smartphones - Batchelor D.

Batchelor D. Symbian os Expleined effective C++ programming for smartphones - Wiley publishing , 2005. - 394 p.
ISBN 0-470-02130-6
Download (direct link): symbianosexpltivec++2005.pdf
Previous << 1 .. 118 119 120 121 122 123 < 124 > 125 126 127 128 129 130 .. 151 >> Next

For illustration purposes, here is just a small part of the RArrayBase class and its subclass RArray (from e32std.h and e32std.inl). The type-unsafe base class (RArrayBase) implements the code logic for the array but cannot be used directly because all its methods are protected. You'll find a detailed discussion of the RArray class, and other Symbian OS container classes, in Chapter 7.
1 You will typically want to use templates when writing a class that manipulates several different types using the same generic code. The code should be agnostic about the type passed into the template parameter, that is, the underlying logic is independent of type. Typical examples of (thin) template classes in Symbian OS are the array classes (I'll discuss RArray shortly), the singly- and doubly-linked list classes (based on TSglQueBase and TDblQueBase) and the circular buffers (based on CCirBufBase).
2 Private inheritance means that the derived class is implemented in terms of the base class. Private inheritance is used when the deriving class uses some of the implemented methods of the base class, but has no direct conceptual relationship with the base class. Using private inheritance allows implementation to be inherited but all the methods of the base class become private members of the deriving class. In effect, the deriving class does not inherit the interface ofthe base class.
THIN TEMPLATES
295
class RArrayBase {
protected:
IMPORT_C RArrayBase(TInt anEntrySize);
IMPORT_C RArrayBase(TInt aEntrySize,TAny* aEntries, Tint aCount); IMPORT_C TAny* At(TInt anIndex) const;
IMPORT_C TInt Append(const TAny* anEntry);
IMPORT_C TInt Insert(const TAny* anEntry, TInt aPos);
};
The templated RArray class privately inherits the implementation and defines a clear, usable API for clients. The API is defined inline and uses the base class implementation. Elements of the array are instances of the template class.
template <class T>
class RArray : private RArrayBase {
public:
inline RArray();
inline const T& operator[](TInt anIndex) const; inline T& operator[](TInt anIndex); inline TInt Append(const T& anEntry); inline TInt Insert(const T& anEntry, TInt aPos);
};
template <class T> inline RArray<T>::RArray()
: RArrayBase(sizeof(T))
{}
template <class T>
inline const T& RArray<T>::operator[](TInt anIndex) const {return *(const T*)At(anIndex); } template <class T>
inline T& RArray<T>::operator[](TInt anIndex)
{return *(T*)At(anIndex); } template <class T>
inline TInt RArray<T>::Append(const T& anEntry)
{return RArrayBase::Append(&anEntry);} template <class T>
inline TInt RArray<T>::Insert(const T& anEntry, TInt aPos)
{return RArrayBase::Insert(&anEntry,aPos);}
Use of the class is then straightforward:
void TestRArray()
{
const TInt arraySize = 3;
RArray<TInt> myArray(arraySize);
for (TInt index = 0; index<arraySize; index++)
{
296
THIN TEMPLATES
myArray.Append(index);
}
Tint count = myArray.Count();
ASSERT(arraySize==count);
for (index = 0; index<arraySize; index++)
{
ASSERT(myArray[index]==index);
}
}
For another example of the thin template pattern in Symbian OS, consider the TBufC and TBuf descriptor classes discussed in Chapter 5. These classes are templated on an integer, the value of which is used as the variable which determines the maximum statically-allocated length of the buffer. In this case, the inheritance model is public and the derived class publicly inherits the base class implementation (whereas the previous example used private inheritance to gain access to the implementation without inheriting the behavior).
The constructors of the derived TBufC16 class, and other functions that use the template parameter, are declared inline. I've shown the constructors for the base and derived classes below (from e32des16.h and e32std.inl):
class TBufCBase16 : public TDesC16 {
protected:
IMPORT_C TBufCBase16();
inline TBufCBase16(TInt aLength);
IMPORT_C TBufCBase16(const TUint16 *aString,TInt aMaxLength);
IMPORT_C TBufCBase16(const TDesC16 &aDes,TInt aMaxLength);
};
template <TInt S>
class TBufC16 : public TBufCBase16 {
public:
inline TBufC16();
inline TBufC16(const TUint16 *aString); inline TBufC16(const TDesC16 &aDes);
};
template <TInt S>
inline TBufC16<S>::TBufC16()
: TBufCBase16()
{}
template <TInt S>
inline TBufC16<S>::TBufC16(const TUint16 *aString)
: TBufCBase16(aString,S)
{}
template <TInt S>
inline TBufC16<S>::TBufC16(const TDesC16 &aDes)
SUMMARY
297
: TBufCBase16(aDes,S) {}
19.1 Summary
This chapter explained why C++ templates are ideal for reusable typesafe but type-agnostic code, but have the disadvantage that they can increase their clients' code size quite considerably. For each templated class, every time a different type is used, separate code is generated for every templated function. Furthermore, this code duplication occurs in each client DLL or compilation unit using the templated class. This can cause significant code bloat unless the number of different types that are used with the templated class is limited, the code generated is small, and it is guaranteed that only a few clients will use the templated class.
Previous << 1 .. 118 119 120 121 122 123 < 124 > 125 126 127 128 129 130 .. 151 >> Next