Symbian3/SDK/Source/GUID-9E0DCB19-5775-5E23-B758-163D747A71C9.dita
author Dominic Pinkman <dominic.pinkman@nokia.com>
Tue, 20 Jul 2010 12:00:49 +0100
changeset 13 48780e181b38
parent 0 89d6a7a84779
permissions -rw-r--r--
Week 28 contribution of SDK documentation content. See release notes for details. Fixes bugs Bug 1897 and Bug 1522.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
     1
<?xml version="1.0" encoding="utf-8"?>
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
     2
<!-- Copyright (c) 2007-2010 Nokia Corporation and/or its subsidiary(-ies) All rights reserved. -->
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
     3
<!-- This component and the accompanying materials are made available under the terms of the License 
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
     4
"Eclipse Public License v1.0" which accompanies this distribution, 
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
     5
and is available at the URL "http://www.eclipse.org/legal/epl-v10.html". -->
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
     6
<!-- Initial Contributors:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
     7
    Nokia Corporation - initial contribution.
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
     8
Contributors: 
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
     9
-->
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    10
<!DOCTYPE concept
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    11
  PUBLIC "-//OASIS//DTD DITA Concept//EN" "concept.dtd">
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    12
<concept xml:lang="en" id="GUID-9E0DCB19-5775-5E23-B758-163D747A71C9"><title>Multiple Inheritance and Interfaces </title><prolog><metadata><keywords/></metadata></prolog><conbody><p>Multiple inheritance is a powerful aspect of C++. This topic explains its use in Symbian platform C++. </p> <section id="GUID-DB8C6A7D-515F-59E4-B2CD-454ACD203DAC"><title>Overview</title> <p>Experience of multiple inheritance indicates that its benefits are best realised by carefully controlling the ways in which it is used within a system to a few easily understood paradigms. Use of multiple inheritance without such control has usually led to designs that are difficult to understand. </p> <p>Multiple inheritance is used for a single purpose on the Symbian platform: namely, interface protocol definitions. These are used in the following kinds of situation: there is a <i>protocol provider</i> class, and a <i>protocol user</i>. It is desirable that the protocol user be independent of all aspects of the protocol provider, except its ability to provide the specified protocol. Examples of such situations include: </p> <ul><li id="GUID-F092AADB-57BD-5D05-95E9-4A4E482BE49F"><p>an application control is a protocol provider; its menu tree uses the protocol for menu observing. When a menu item has been selected, the menu observing protocol is invoked, so that the application control may handle the menu command. Apart from this, the menu control knows nothing about the application control. </p> </li> <li id="GUID-6257FC9B-96A1-5697-9031-2EAE2543CE8E"><p>an application, such as a spreadsheet, may have an <i>engine</i> which provides protocols for updating and getting its model contents, and a <i>user interface</i>, which uses these protocols to drive the engine. The engine is written with no knowledge of the user interface, and the user interface is written with minimal knowledge of the engine. They interact using a protocol provided by the engine. </p> </li> </ul> <p>To understand why interfaces are used, this page examines in turn: </p> <ul><li id="GUID-38F4E007-C040-5CA0-B2DE-F6BD0E369A0F"><p>the traditional method which uses single inheritance </p> </li> <li id="GUID-25E00997-6A10-5EEF-BAD1-784C9F9B5349"><p>a technique of overcoming the disadvantages of single inheritance, using protocol intermediary classes </p> </li> <li id="GUID-7AAE1568-0FF7-5C3E-98C0-29674C5FABDF"><p>a better technique, which uses multiple inheritance with interface classes </p> </li> <li id="GUID-E81625F6-CD1C-5C54-85E3-B4CF292422E0"><p>the restrictions on C++ multiple inheritance on the Symbian platform </p> </li> </ul> </section> <section id="GUID-099DC498-32E2-573A-9404-A60C55FE0D32"><title>Protocols using classic single inheritance</title> <p>A classical use of single inheritance is to define an abstract protocol from which derived classes may inherit. A base class defines a protocol: </p> <codeblock id="GUID-9BA46070-85BD-5806-A781-A9E7BD0F1CC3" xml:space="preserve">class CProtocol : public CBase
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    13
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    14
public:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    15
    virtual void HandleEvent(TInt aEventCode)=0;
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    16
    };</codeblock> <p>The protocol includes just one function, <codeph>HandleEvent()</codeph>, where the event is defined by an integer event code. </p> <p>A concrete protocol provider class is then derived from this base class. It provides a concrete implementation of the pure virtual function in the base class: </p> <codeblock id="GUID-55ABB36D-2131-570C-A23A-AC02B3F154D5" xml:space="preserve">class CProtocolProvider : public CProtocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    17
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    18
public:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    19
    // construct/destruct
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    20
    static CProtocolProvider* NewLC();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    21
    void Destruct();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    22
    // implement the protocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    23
    void HandleEvent(TInt aEventCode); // handle protocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    24
protected:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    25
    void ConstructL();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    26
    };</codeblock> <p>In addition, there is a protocol user class which knows nothing about the derived <codeph>CProtocolProvider</codeph> class, but it does know about the <codeph>CProtocol</codeph> class and the functions that specify its protocol. It has a function which uses <codeph>HandleEvent()</codeph>: </p> <codeblock id="GUID-30356ABC-7148-5004-B4A4-B55DA1053381" xml:space="preserve">void CProtocolUser::DoSomething(CProtocol* aProtocol)
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    27
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    28
    _LIT(KOutput1,"External system doing something\n");
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    29
    _LIT(KOutput2,"invoking protocol - event 3\n");
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    30
    testConsole.Printf(KOutput1);
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    31
    testConsole.Printf(KOutput2);
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    32
    aProtocol-&gt;HandleEvent(3); // handle an event
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    33
    }</codeblock> <p>The virtual function defined by <codeph>CProtocol</codeph> is provided by <codeph>CProtocolProvider</codeph>. This is the virtual function that is actually executed: </p> <codeblock id="GUID-A718C56C-6555-5D15-9C52-FE4F5E0120ED" xml:space="preserve">void CProtocolProvider::HandleEvent(TInt aEventCode)
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    34
    { // handle an event in the protocol user
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    35
    _LIT(KOutput1,"CProtocolProvider handling event %d\n");
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    36
    testConsole.Printf(KOutput1,aEventCode);
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    37
    }</codeblock> <p>Thus, although the protocol user knows nothing about the derived <codeph>CProtocolProvider</codeph> class, it can invoke its member functions through a pointer to its derived class, using the C++ virtual function mechanism. </p> <p>This code may be used in the following way: </p> <codeblock id="GUID-6355012A-2413-5B0E-811C-BF28A30FDC4F" xml:space="preserve">void doExampleL()
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    38
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    39
    // show use of interface with simple class
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    40
    CProtocolProvider* provider=CProtocolProvider::NewLC();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    41
    CProtocolUser* user=CProtocolUser::NewLC();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    42
    user-&gt;DoSomething(provider);
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    43
    CleanupStack::PopAndDestroy(); // user
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    44
    CleanupStack::PopAndDestroy(); // provider
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    45
    }</codeblock> <p>In the function call, the <codeph>provider</codeph> pointer is cast to its <codeph>CProtocol*</codeph> base class, as required by <codeph>CProtocolUser::DoSomething()</codeph>. </p> <p>The advantages of this method are </p> <ul><li id="GUID-E9B232B6-42F9-5A34-A9E9-116D82D269E9"><p>it achieves independence of the protocol user from the specific protocol provider </p> </li> </ul> <p>This was the goal we set out to achieve. However, this method has a serious disadvantage: </p> <ul><li id="GUID-FA6702D5-AE01-5367-ABD0-AF92892BE871"><p>it forces the protocol provider to be <i>derived</i> from a protocol base class </p> </li> <li id="GUID-1B4D6785-1BE5-534B-B4FA-B0FADA87E268"><p>however, if <i>more than one</i> protocol must be provided by the provider class, the only solution is to include all the protocols into a single umbrella protocol, and to derive the provider class from that. This is bad encapsulation. Firstly, the base class can become quite large and it can be unclear why it contains so many member functions, or which function belongs to which protocol. Secondly, it may be desirable to have another provider class which provides some of the protocols provided by the first class, and others in addition. To support this requires an even larger umbrella protocol. </p> </li> </ul> <p>The straightforward method of providing protocols by strict single inheritance often leads to large base classes, representing many protocols which should really be independent of one another. </p> </section> <section id="GUID-75614A8E-B613-5E2E-AF34-EFAF854DCD92"><title>Protocols using an intermediate class</title> <p>Some of these disadvantages can be overcome by using an intermediary object which represents the protocol, and has a pointer to the protocol provider. The base protocol class is essentially the same: </p> <codeblock id="GUID-F8A493FA-77EE-5C9D-9BB2-DB2547558EAF" xml:space="preserve">class TProtocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    46
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    47
public:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    48
    virtual void HandleEvent(TInt aEventCode)=0;
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    49
    };</codeblock> <p>but there is now a derived class for use with the <codeph>CProtocolProvider</codeph> only: </p> <codeblock id="GUID-9448AEDC-5B25-51FC-BCF8-E1C747DE89F3" xml:space="preserve">class TProtocolProviderIntermediary : public TProtocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    50
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    51
public:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    52
    // construct
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    53
    TProtocolProviderIntermediary(CProtocolProvider* aRealProvider);
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    54
    // protocol itself
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    55
    void HandleEvent(TInt aEventCode);
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    56
private:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    57
    CProtocolProvider* iRealProvider; // real provider
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    58
    };</codeblock> <p>This class provides the protocol as far as the protocol user is concerned. The concrete implementation of <codeph>HandleEvent()</codeph> just passes the function call to the real protocol provider class, which has a non-virtual <codeph>DoHandleEvent()</codeph> to provide the required functionality: </p> <codeblock id="GUID-4A035C1A-ABBD-5557-BBB8-A2D2AAABF85E" xml:space="preserve">void TProtocolProviderIntermediary::HandleEvent(TInt aEventCode)
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    59
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    60
    iRealProvider-&gt;DoHandleEvent(aEventCode);
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    61
    }</codeblock> <p>With this system, <codeph>CProtocolProvider</codeph> is derived, not from the protocol definition class, but from <codeph>CBase</codeph>: </p> <codeblock id="GUID-63868CC8-2FAD-5013-BE90-0C258EC79319" xml:space="preserve">class CProtocolProvider : public CBase
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    62
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    63
public:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    64
    // construct/destruct
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    65
    static CProtocolProvider* NewLC();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    66
    void Destruct();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    67
    // implement the protocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    68
    void DoHandleEvent(TInt aEventCode); // handle protocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    69
protected:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    70
    void ConstructL();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    71
public:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    72
    TProtocolProviderIntermediary* iProviderIntermediary;
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    73
    };</codeblock> <p>The <codeph>TProtocolProviderIntermediary</codeph> is constructed by the <codeph>CProtocolProvider</codeph> ’s constructor, and destroyed by its destructor. For this reason, the <codeph>TProtocolProviderIntermediary</codeph> is a <codeph>T</codeph> class: it does not own the <codeph>CProtocolProvider</codeph>, and cannot be orphaned. </p> <p>When a function in the protocol user requiring the protocol provider is called, it must now be called passing the intermediary object as a parameter: </p> <codeblock id="GUID-EDE3C9FC-71AF-59B6-B339-0819FE6AA578" xml:space="preserve">LOCAL_C void doExampleL()
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    74
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    75
    // show use of interface with simple class
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    76
    CProtocolProvider* provider=CProtocolProvider::NewLC();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    77
    CProtocolUser* user=CProtocolUser::NewLC();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    78
    user-&gt;DoSomething(provider-&gt;iProviderIntermediary);
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    79
    CleanupStack::PopAndDestroy(); // user
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    80
    CleanupStack::PopAndDestroy(); // provider
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    81
    }</codeblock> <p>The protocol user’s <codeph>DoSomething()</codeph> is essentially as it was before, except that its parameter is now a <codeph>TProtocol*</codeph>. Thus, the user knows only about the base <codeph>TProtocol</codeph> class. The virtual function mechanism causes the derived intermediary’s <codeph>HandleEvent()</codeph> to be called, and this function passes on the request to the real protocol provider’s <codeph>DoHandleEvent()</codeph>. </p> <p>This method solves the problems associated with using only single inheritance: </p> <ul><li id="GUID-67EBED78-BA71-5D6E-8642-0EBE413EAE48"><p>any number of protocols may be supported, and separately encapsulated, by a particular class: each protocol requires an intermediary class, and objects of each intermediary class point to corresponding objects of the real protocol provider class </p> </li> <li id="GUID-D6D043F9-86D3-5486-B584-24BE27E58D3A"><p>no large base classes are needed to provide umbrellas for several protocols </p> </li> </ul> <p>However, it has a serious disadvantage: </p> <ul><li id="GUID-66694BCD-5C3F-505F-9B51-A4D37801F6B1"><p>it is awkward: not only does each protocol require an abstract class (which cannot be avoided), but also, at each point in the derivation tree at which a protocol is introduced, a derived protocol class must be written which implements the protocol for the relevant class which really provides the protocol: further, the derived protocol object and the real protocol provider must be linked </p> </li> <li id="GUID-363DEB0D-E3B9-513C-ADEC-654C315390B4"><p>if there are many classes which use many protocols in this way, not only is the method cumbersome to program, but it is uneconomical on memory, since each derived protocol class object requires at least two machine words of heap memory. This consideration becomes more serious if there are more small real protocol providers, providing many different protocols. </p> </li> </ul> </section> <section id="GUID-EBBC826E-BD8C-5753-9F86-BE601C8E1852"><title>Protocols using interface classes</title> <p>These problems can be overcome by using multiple inheritance. A base <codeph>MProtocol</codeph> class specifies the protocol: </p> <codeblock id="GUID-BAA67F7D-95A9-52E7-80B5-CA0EB447FE55" xml:space="preserve">class MProtocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    82
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    83
public:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    84
    virtual void HandleEvent(TInt aEventCode)=0;
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    85
    };</codeblock> <p>This time, however, the protocol provider is derived both from <codeph>CBase</codeph>  <i>and</i> from <codeph>MProtocol</codeph>: </p> <codeblock id="GUID-2768C379-BE30-58E3-8EB3-EFB9CEC1CFD3" xml:space="preserve">class CProtocolProvider : public CBase, public MProtocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    86
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    87
public:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    88
    // construct/destruct
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    89
    static CProtocolProvider* NewLC();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    90
    void Destruct();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    91
    // implement the protocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    92
    void HandleEvent(TInt aEventCode); // handle protocol
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    93
protected:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    94
    void ConstructL();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    95
    };</codeblock> <p>The protocol provider class provides a concrete implementation of the <codeph>HandleEvent()</codeph> function required by the protocol. The user class may now be invoked as follows: </p> <codeblock id="GUID-88E052C2-7796-5E30-A5D4-C0D8640E6E98" xml:space="preserve">LOCAL_C void doExampleL()
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    96
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    97
    // show use of interface with simple class
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    98
    CProtocolProvider* provider=CProtocolProvider::NewLC();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
    99
    CProtocolUser* user=CProtocolUser::NewLC();
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   100
    user-&gt;DoSomething(provider);
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   101
    CleanupStack::PopAndDestroy(); // user
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   102
    CleanupStack::PopAndDestroy(); // provider
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   103
    }</codeblock> <p>The <codeph>DoSomething()</codeph> function requires an <codeph>MProtocol*</codeph> parameter. C++ casts the <codeph>CProtocolProvider*
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   104
          provider</codeph> pointer down to an <codeph>MProtocol*</codeph>, because <codeph>MProtocol</codeph> is one of the base classes of <codeph>CProtocolProvider</codeph>. When <codeph>DoSomething()</codeph> invokes <codeph>HandleEvent()</codeph>, the C++ virtual function mechanism ensures that it is <codeph>CProtocolProvider</codeph> ’s <codeph>HandleEvent()</codeph> that is actually called. Thus, the user may use the protocol, without knowing anything specific about the concrete protocol provider class. </p> <p>This method achieves the intended goals: </p> <ul><li id="GUID-1E2C3B6E-DD7E-511E-91EF-324215FC11EB"><p>the protocol user is dependent on the protocol, but not on any particular provider </p> </li> <li id="GUID-03479EC5-0AEC-5D44-B601-95351773D2A3"><p>the protocol can be introduced into a class hierarchy at any desired point, by multiply inheriting from a base class and one or more interface classes </p> </li> <li id="GUID-E6D3B4B5-DDEB-50D0-9052-6D0149CA1298"><p>full encapsulation of different protocols is achieved </p> </li> <li id="GUID-DC84E8E4-3DB8-52C2-80EC-CEF35C25C15F"><p>there is no inconvenient intermediate class, with its programming difficulties and wasteful memory use </p> </li> </ul> <p>Because protocols may be mixed into the derivation hierarchy of conventional classes at any convenient point in the hierarchy, such protocol specification classes are sometimes also called mixins, the origin of the prefix <codeph>M</codeph>. </p> </section> <section id="GUID-66C2EC3E-8047-5A0C-AFC5-8D486E67A1E1"><title>Restrictions on the use of multiple inheritance</title> <p>The use of multiple inheritance is restricted to interfaces used as described above. C++’s full multiple inheritance facilities are unnecessarily complex. This is perhaps recognised by the OO community now. Java, for instance, allows only single inheritance, but the <codeph>interface</codeph> and <codeph>implements</codeph> keywords support the same facilities as are provided by <codeph>M</codeph> classes. The restrictions are given in more detail here. </p> <p>Firstly, <codeph>M</codeph> classes primarily define protocols, not implementations. In particular, they should not have any member data. The restriction implies that certain types of behaviour (e.g., that of active objects, see <xref href="GUID-890F06C6-DE32-5EB1-BF0F-D41794F47AE1.dita">Active objects</xref>) may <i>not</i> be encapsulated in an interface, but must be derived in the conventional way. </p> <p>Secondly, a <codeph>C</codeph> class may be derived from one other <codeph>C</codeph> class, and zero or more <codeph>M</codeph> classes. This restriction reflects the fact that multiple inheritance is only to be used for interfaces. It implies that it is still possible to uniquely identify a primary inheritance tree (the <codeph>C</codeph> class hierarchy), with interfaces as a side feature. If arbitrary multiple inheritance were allowed, it would be impossible to identify a primary inheritance tree. The restriction also guarantees that no <codeph>C</codeph> class will be a multiple base class, which makes it unnecessary to consider the complications of multiple base class inclusion, virtual inheritance, etc. </p> <p>Thirdly, the <codeph>C</codeph> class must be the first specified class in any base class list. This emphasises the primary inheritance tree and, importantly, it makes conversions between any <codeph>C</codeph> class (including those with interfaces) and <codeph>void*</codeph> pointers freely possible. Admittedly, the C++ standards do not mandate that object layout follows the order in which base classes are specified, but in practice this is the case for most compilers, including those used for the Symbian platform. </p> <p>Fourthly, no <codeph>M</codeph> class may be mixed in more than once in any class, either as a direct base or as a base of any of its primary base classes. To put it another way: when deriving a <codeph>C</codeph> class <codeph>CD</codeph> from a base class <codeph>CB</codeph>, you may not mix in any <codeph>M</codeph> class <codeph>MP</codeph> which has already been mixed into the derivation of <codeph>CB</codeph>. This reflects the fact that <codeph>CB</codeph> already supports the protocol defined by <codeph>MP</codeph>: there is nothing to gain from mixing in this protocol class again. In addition, it makes it unnecessary to consider the complications of multiple base class inclusion, virtual inheritance, etc. </p> <p>Finally, although it is legal to derive one <codeph>M</codeph> class from another, it is not legal to include a protocol twice by including both it and a derived protocol into a <codeph>C</codeph> class, at any point in the <codeph>C</codeph> class’s base class graph. To put it another way, if there is a class <codeph>MD</codeph> derived from <codeph>MB</codeph>, then a <codeph>C</codeph> class cannot include both <codeph>MB</codeph> and <codeph>MD</codeph>. This is because any function in the <codeph>C</codeph> class which provided an implementation of <codeph>MB</codeph> protocol could conflict with the implementation of <codeph>MD</codeph> protocol. </p> </section> <section><title>Example uses</title> <p><b>Callbacks</b> </p> <p>A special case of an interface is the callback. In this situation, one class performs a certain function for another and, when this is done, calls a single function in the requesting class, to indicate that the requested operation is complete. This call-back function represents a protocol: the requesting class is the provider, and the performing class is the user. Apart from this, the performing class need know little or nothing about the requesting class. This is an ideal situation for a interface. </p> <p><b>Two-way use</b> </p> <p>So far, we have discussed interfaces in the context where one class provides services according to a given protocol, and another uses those services. In a more general case, two classes (or systems of classes) may require services from each other, so that there is two-way interaction. </p> <p>Services are always provided according to a protocol. The protocol can be provided using any of the techniques described in this document: </p> <ul><li id="GUID-7C71224B-9E1D-5277-B58F-C3B51E48D91C"><p>conventional derivation, which is most appropriate where the protocol characterises a class’s main purpose </p> </li> <li id="GUID-F9D18F75-C44B-5E52-8140-454A79AFF31F"><p>interface inheritance, which is most appropriate where a protocol may be a characteristic of many classes, but where these classes have diverse main purposes </p> </li> <li id="GUID-642E0CAD-5804-5364-9BDA-2C0AC334B670"><p>intermediary objects, which may be appropriate where an interface would otherwise be used, but when multiple inheritance is disallowed, or inconvenient for some other reason </p> </li> </ul> <p><b>Observers</b> </p> <p>GUI applications use menus to present a user interface for selecting options. When an option has been chosen, the menu bar should forward a command somewhere by calling a member function of some class. The only thing that is important to the menu bar is that some object exists which can handle the command: beyond that, nothing matters about the object. </p> <codeblock id="GUID-3525BD39-699B-5977-A36B-A8B2355AA1DD" xml:space="preserve">class CEikMenuBar ...
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   105
    {
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   106
public:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   107
    ConstructL(MEikMenuObserver* aObserver, ...);
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   108
    // ...
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   109
private:
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   110
    MEikMenuObserver* iObserver;
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   111
    // ...
89d6a7a84779 Initial contribution of Documentation_content according to Feature bug 1266 bug 1268 bug 1269 bug 1270 bug 1372 bug 1374 bug 1375 bug 1379 bug 1380 bug 1381 bug 1382 bug 1383 bug 1385
Dominic Pinkman <Dominic.Pinkman@Nokia.com>
parents:
diff changeset
   112
    }</codeblock> <p>A menu bar therefore <i>uses</i> a menu observer. This is passed in as a parameter at construction, stored as member data, and used when an option has been selected. The menu observer interface is defined by the menu component, as the <codeph>MEikMenuObserver</codeph> class. </p> <p>This interface is implemented by the app UI (which also does many other things, which are irrelevant to menus). So, <codeph>CEikAppUi</codeph> implements menu observer interface by deriving from <codeph>MEikMenuObserver</codeph>: </p> <codeblock id="GUID-FD7DE6CD-31ED-5F58-BA37-F6DA5CFCB6B7" xml:space="preserve">class CEikAppUi : public CCoeAppUi, MEikMenuObserver</codeblock> <p>The app UI has a menu bar, and when it constructs the menu bar, the app UI passes itself to the menu bar, as the observer: </p> <codeblock id="GUID-86E37F76-3B90-5179-9AAC-27B30C30735E" xml:space="preserve">iMenuBar-&gt;ConstructL(this, ...);</codeblock> <p>C++ causes the <codeph>this</codeph> to be cast into the appropriate base class—in this case, an <codeph>MEikMenuObserver</codeph> —automatically. </p> </section> </conbody></concept>