Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Interfacing with C plus plus-programing communication with microcontrolers (K. Bentley, 2006)

.pdf
Скачиваний:
192
Добавлен:
12.08.2013
Размер:
3.18 Mб
Скачать

12 DATA ACQUISITION WITH OPERATOR OVERLOADING 377

only carries out member-by-member copying, but also makes copies of any portions of memory pointed to by pointer data members. Having such a copy constructor will change the situation shown in Figure 12-1 to that shown in Figure 12-3.

Now when the destructor is called to discard the copies, the original data will be unaffected and the outcome will be as shown in Figure 12-4.

Object A

Object B

NumInts

NumInts

ArrayPointer

ArrayPointer

Memory dynamically allocated by the constructors

Figure 12-4 The original data areas are not destroyed by the destructor.

The header file intarray.h contains the definition of the copy constructor as given in Listing 12-4.

Listing 12-4 The header file intarray.h with user supplied copy constructor.

#ifndef IntarrayH #define IntarrayH

class IntArray

{

private:

int NumInts;

int* ArrayPointer;

public:

IntArray(); IntArray(int numints);

IntArray(const IntArray& intArray);

~IntArray();

void EnterArray(); void PrintArray();

};

#endif

The heading of the copy constructor is:

378 12 DATA ACQUISITION WITH OPERATOR OVERLOADING

IntArray(const IntArray& intArray);

Remember that constructors do not have return values. The parameter passed to the copy constructor is the same type as the class the copy constructor belongs to and must be passed by reference. If it is passed by value, then a copy will be created by a call to the copy constructor. To pass a parameter to that copy constructor by value, another copy has to be created and so on – an endless sequence of function calls. Therefore, the parameter passed to the copy constructor must be passed by reference. The keyword const is used to protect the parameter passed by reference. Therefore, no changes will be made to the parameter being passed.

The complete function file is given in Listing 12-5.

Listing 12-5 The function file intarray.cpp for the IntArray class.

#include <iostream.h> #include "intarray.h"

IntArray::IntArray()

{

NumInts = 0; ArrayPointer = NULL;

}

IntArray::IntArray(int numints)

{

if(numints <=0)

{

NumInts = 0; ArrayPointer = NULL;

}

else

{

NumInts = numints;

ArrayPointer = new int[NumInts];

}

}

IntArray::IntArray(const IntArray& intArray)

{

NumInts = intArray.NumInts; ArrayPointer = new int[NumInts]; for(int i=0; i < NumInts; i++)

*(ArrayPointer+i) = *(intArray.ArrayPointer +i);

}

12 DATA ACQUISITION WITH OPERATOR OVERLOADING 379

IntArray::~IntArray()

{

if(ArrayPointer !=NULL)

{

delete ArrayPointer; ArrayPointer = NULL;

}

}

void IntArray::EnterArray()

{

cout << "Enter " << NumInts << " integer values." << endl;

for(int i = 0; i < NumInts; i++) cin >> *(ArrayPointer + i);

}

void IntArray::PrintArray()

{

for(int i =0; i < NumInts; i++)

cout << *(ArrayPointer + i) << '\t'; cout << endl;

}

A main() function can be written with an explicit call to the copy constructor and an explicit call to the destructor to destroy the object generated by the copy constructor. The program copycnst.cpp given in Listing 12-6 demonstrates that the call to the destructor does not destroy the original data.

Listing 12-6 This program tests the user supplied copy constructor - copycnst.cpp.

#include <iostream.h> #include <conio.h>

#include "intarray.h"

void main()

{

IntArray A(5);

A.EnterArray();

cout << "A " ; A.PrintArray(); //

Print array A.

getch();

B(A);

//

Call copy constructor.

IntArray

380 12 DATA ACQUISITION WITH OPERATOR OVERLOADING

cout << "B "; B.PrintArray(); // Print array B. B.~IntArray(); // Destroy array B. // Print array A again, check data is intact.

cout << "A "; A.PrintArray();

}

Executable File Generation

 

Required Files

 

Listing No.

 

Project File Contents

 

 

copycnst.cpp

 

Listing 12-6

 

copycnst.cpp

 

 

 

 

 

 

intarray.cpp

 

Listing 12-5

 

intarray.cpp

 

 

intarray.h

 

Listing 12-4

 

 

 

12.2.5 Overloading Operators as Member Functions

In this section we will be overloading the >> operator for the ADC class so that it can be used to carry out an analog-to-digital conversion and store the result in a variable. To do this the class definition in the header file adc.h must be changed to include the member function that overloads the operator. We will follow the syntax for function headings shown in Table 12-2 to produce the new header file for the ADC class given in Listing 12-7.

The parameter passed to the operator overloading function has been passed by reference. This allows the passed parameter to be changed within the function and the parameter in the calling environment will now hold the new value read from the ADC when the function exits.

Listing 12-7 Header file adc.h shows operator overloading as a member function.

#ifndef AdcH #define AdcH #include "pport.h"

class ADC : public ParallelPort

{

private:

unsigned char ADCValue;

public:

ADC(int baseaddress=0x378); unsigned char ADConvert(); unsigned char GetADCValue();

void operator>>(unsigned char& value);

};

#endif

12 DATA ACQUISITION WITH OPERATOR OVERLOADING 381

The original adc.cpp file from Listing 11-4 is then modified to that given in Listing 12-8.

Listing 12-8 Function file adc.cpp associated with header file in Listing 12-7.

#include "adc.h"

ADC::ADC(int baseaddress) : ParallelPort(baseaddress)

{

ADCValue = 0;

}

unsigned char ADC::ADConvert()

{

WritePort2(0x01);

WritePort2(0x00);

WritePort2(0x01);

WritePort2(0x03);

ADCValue = ReadPort1() & 0xF0;

WritePort2(0x01);

ADCValue += (ReadPort1() >> 4) & 0x0F;

return ADCValue;

}

unsigned char ADC::GetADCValue()

{

return ADCValue;

}

void ADC::operator>>(unsigned char& value)

{

ADConvert(); value = ADCValue;

}

Note: although the >> operator needs two arguments, we have passed only one parameter. This parameter becomes the operand to the right of the >> operator. The operand to the left of the >> operator is the object of type ADC (see the main() function in Listing 12-9). Furthermore, within the function’s body we have used the statements:

ADConvert(); value = ADCValue;

rather than the statement:

value = ADConvert();

382 12 DATA ACQUISITION WITH OPERATOR OVERLOADING

We deliberately do this to keep the program (which overloads an operator as a member function) as similar as possible to the next program (which overloads an operator as a non-member function). The main() function shown in Listing 12-9 demonstrates use of the overloaded operator as a member function.

Listing 12-9 main() function file ovld.cpp uses the overloaded operator >>.

#include <bios.h> #include <conio.h>

#include "adc.h"

void main()

{

ADC Adc;

int Quit = 0, key; unsigned char Value;

clrscr();

while(!Quit)

{

gotoxy(10,10);

Adc >> Value;

cprintf("The ADC output is %10d\a",(int)Value);

if(bioskey(1)!=0)

{

key = bioskey(0);

if(key == 0x2d00) Quit = 1; // Alt-X key

}

}

}

Executable File Generation

 

Required Files

 

Listing No.

 

Project File Contents

 

 

pport.cpp

 

Listing 10-8

 

pport.cpp

 

 

 

 

 

pport.h

 

Listing 10-7

 

adc.cpp

 

adc.cpp

 

Listing 12-8

 

 

adc.h

Listing 12-7

 

 

 

ovld.cpp

Listing 12-9

 

ovld.cpp

 

12 DATA ACQUISITION WITH OPERATOR OVERLOADING 383

The operation of this program can be verified with the interface board by connecting the potentiometer output to the input of the ADC.

12.2.6 Overloading Operators as non-member f’ns

The operator overloading function will now be moved outside the class definition as an ordinary function to create the header file adc.h given in Listing 12-10.

Listing 12-10 File adc.h shows operator overloading as a non-member function.

#ifndef AdcH #define AdcH

#include "pport.h"

class ADC : public ParallelPort

{

private:

unsigned char ADCValue;

public:

ADC(int baseaddress=0x378); unsigned char ADConvert(); unsigned char GetADCValue();

};

// declaration of the non-member function

void operator>>(ADC adc, unsigned char& value);

#endif

Listing 12-11 shows the function file associated with the above header file.

Listing 12-11 Function file adc.cpp associated with the header file in Listing 12-10.

#include "adc.h"

ADC::ADC(int baseaddress) : ParallelPort(baseaddress)

{

ADCValue = 0;

}

unsigned char ADC::ADConvert()

{

WritePort2(0x01);

WritePort2(0x00);

WritePort2(0x01);

WritePort2(0x03);

ADCValue = ReadPort1() & 0xF0;

384 12 DATA ACQUISITION WITH OPERATOR OVERLOADING

WritePort2(0x01);

ADCValue += (ReadPort1() >> 4) & 0x0F;

return ADCValue;

}

unsigned char ADC::GetADCValue()

{

return ADCValue;

}

void operator>>(ADC adc, unsigned char& value)

{

adc.ADConvert();

value = adc.GetADCValue();

}

Executable File Generation

 

Required Files

 

Listing No.

Project File Contents

 

pport.cpp

 

Listing 10-8

pport.cpp

 

pport.h

 

Listing 10-7

adc.cpp

 

adc.cpp

 

Listing 12-11

ovld.cpp

 

adc.h

 

Listing 12-10

 

 

ovld.cpp

 

Listing 12-9

 

 

 

 

The operator overloading function has now been passed two parameters unlike the case described in Section 12.2.5. The first parameter becomes the operand to the left of the operator >> and the second parameter becomes the operand to the right. Since the function does not belong to any class, the first parameter must be used explicitly. We cannot use the following statement in this function because we do not have access to the private data member ADCValue:

value = adc.ADCValue;

Instead, the public member function GetADCValue() must be called. The same main() function (Listing 12-9) can now be used provided that its #include “adc.h” statement includes the header file given in Listing 12-10, and is compiled and linked with the function file given in Listing 12-11.

12.2.7 Friend Functions

Ordinary non-member functions can be declared as friends of a particular class to eliminate the difficulties associated with accessing private data members. In this case the non-member friend function will have unrestricted access to all data members of the class that it is declared in. The friend functions can be viewed as

12 DATA ACQUISITION WITH OPERATOR OVERLOADING 385

public functions of the class that do not need to be attached (tagged) to the object using the membership access operators (i.e . or ->). Careful use of friend functions can facilitate some tasks such as input/output streaming we will be discussing shortly. To demonstrate the use of friend functions, we can modify the header file given in Listing 12-10 to become that given in Listing 12-12.

Listing 12-12 Use of friend functions - adc.h.

#ifndef AdcH #define AdcH

#include "pport.h"

class ADC : public ParallelPort

{

private:

unsigned char ADCValue;

public:

ADC(int baseaddress=0x378); unsigned char ADConvert(); unsigned char GetADCValue();

friend void operator>>(ADC adc, unsigned char& value);

};

#endif

Since the operator overloading function is a friend of the ADC class, it will now have access to the private data member ADCValue. Therefore, instead of the line:

value = adc.GetADCValue();

we can now use:

value = adc.ADCValue;

This avoids a function call and so speeds up program execution. The associated function file is shown in Listing 12-13.

Listing 12-13 Function file adc.cpp for the header file in Listing 12-12.

#include "adc.h"

ADC::ADC(int baseaddress) : ParallelPort(baseaddress)

{

ADCValue = 0;

}

unsigned char ADC::ADConvert()

{

WritePort2(0x01);

386 12 DATA ACQUISITION WITH OPERATOR OVERLOADING

WritePort2(0x00);

WritePort2(0x01);

WritePort2(0x03);

ADCValue = ReadPort1() & 0xF0;

WritePort2(0x01);

ADCValue += (ReadPort1() >> 4) & 0x0F;

return ADCValue;

}

unsigned char ADC::GetADCValue()

{

return ADCValue;

}

void operator>>(ADC adc, unsigned char& value)

{

adc.ADConvert(); value = adc.ADCValue;

}

Executable File Generation

 

Required Files

 

Listing No.

 

Project File Contents

 

 

pport.cpp

 

Listing 10-8

 

pport.cpp

 

 

 

 

 

 

pport.h

Listing 10-7

 

adc.cpp

 

 

adc.cpp

Listing 12-13

 

 

adc.h

Listing 12-12

 

 

 

ovld.cpp

Listing 12-9

 

ovld.cpp

 

In the previous sections we implemented operator overloading to carry out analog- to-digital conversion and stored the resulting value in a variable. We overloaded the >> operator to accomplish this ‘input’ operation. Next we will overload the << operator to output the result of an anlog-to-digital conversion to the screen or to a file. Before we do this, we need to have a fundamental understanding of I/O streams and pass-through objects.

12.2.8 I/O Streams

I/O streams can be viewed as a sequential transfer of one or more objects between two locations. Examples of such transfers could be data generated by the keyboard to a program, program data to screen, program data to a file, data from a file to a program, etc. C++ software provides a number of object classes and a large variety of functions to facilitate input/output streaming of objects. Output streams can be