Escolar Documentos
Profissional Documentos
Cultura Documentos
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// Fig. 22.1: fig22_01.cpp // Demonstrating operator const_cast. #include <iostream> using std::cout; using std::endl; // class ConstCastTest definition class ConstCastTest { public: void setNumber( int ); int getNumber() const; void printNumber() const; private: int number; }; // end class ConstCastTest
Outline
fig22_01.cpp (1 of 2)
// set number void ConstCastTest::setNumber( int num ) { number = num; } // return number int ConstCastTest::getNumber() const { return number; }
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
// output number void ConstCastTest::printNumber() const { cout << "\nNumber after modification: "; // cast away const-ness to allow modification const_cast< ConstCastTest * >( this )->number--; cout << number << endl; } // end printNumber
Outline
Cast away the const-ness fig22_01.cpp the this pointer. This allows (2 of 2) the data to be modified. fig22_01.cpp output (1 of 1)
cout << "Initial value of number: " << test.getNumber(); test.printNumber(); return 0; } // end main
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 x
// Fig. 22.2: fig22_02.cpp // Demonstrating operator reinterpret_cast. #include <iostream> using std::cout; using std::endl; int main() { int x = 120; int *ptr = &x;
Outline
fig22_02.cpp (1 of 1)
Create an int *. Cast it to a char * for printing. 120 is the ASCII value of 'x'.
fig22_02.cpp output (1 of 1)
// use reinterpret_cast to cast from int * to char * cout << *reinterpret_cast< char * >( ptr ) << endl; return 0; } // end main
Examples
using namespace std Discouraged by some programmers, because includes entire contents of std using namespace std::cout Can write cout instead of std::cout
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// Fig. 22.3: fig22_03.cpp // Demonstrating namespaces. #include <iostream> using namespace std; int integer1 = 98; // use std
10
Note the using statement. This includes all of std, allowing us to use cout and namespace endl.
Outline
fig22_03.cpp (1 of 3)
// global variable
// create namespace Example namespace Example { // declare two constants and one const double PI = 3.14159; const double E = 2.71828; int integer1 = 8; void printValues(); // nested namespace namespace Inner {
Create a new namespace, Example. Note that it has a variable integer1, variable different from the global integer1.
// prototype Note
// define enumeration enum Years { FISCAL1 = 1990, FISCAL2, FISCAL3 }; } } // end Inner
// end Example
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
11
// create unnamed namespace namespace { double doubleInUnnamed = 88.22; } // end unnamed namespace
// declare
Create an unnamed Outline namespace. Its variables are global. variable fig22_03.cpp (2 of 3)
int main() { // output value doubleInUnnamed of unnamed namespace cout << "doubleInUnnamed = " << doubleInUnnamed; // output global variable cout << "\n(global) integer1 = " << integer1; // output values of Example namespace cout << "\nPI = " << Example::PI << "\nE = " << Example::E << "\ninteger1 = " << Example::integer1 << "\nFISCAL3 = " << Example::Inner::FISCAL3 << endl; Example::printValues(); return 0; } // end main // invoke printValues function
54 55 56 57 58 59 60 61 62 63 64
12
// display variable and constant values void Example::printValues() { cout << "\nIn printValues:\ninteger1 = " << integer1 << "\nPI = " << PI << "\nE = " << E << "\ndoubleInUnnamed = " << doubleInUnnamed << "\n(global) integer1 = " << ::integer1 << "\nFISCAL3 = " << Inner::FISCAL3 << endl; } // end printValues
Outline
fig22_03.cpp (3 of 3)
doubleInUnnamed = 88.22 (global) integer1 = 98 PI = 3.14159 E = 2.71828 integer1 = 8 FISCAL3 = 1992 In printValues: integer1 = 8 PI = 3.14159 E = 2.71828 doubleInUnnamed = 88.22 (global) integer1 = 98 FISCAL3 = 1992
13
Outline
fig22_03.cpp output (1 of 1)
14
15
not_eq
Inequality
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// Fig. 22.5: fig22_05.cpp // Demonstrating operator keywords. #include <iostream> using std::cout; using std::endl; using std::boolalpha; #include <iso646.h> int main() { int a = 2; int b = 3; cout << << << << << << << << << << << << boolalpha " a and "\n a or "\n not "\na not_eq "\na bitand "\na bit_or "\n a xor "\n compl "\na and_eq "\n a or_eq "\na xor_eq
16
Outline
fig22_05.cpp (1 of 2)
28 29 30 31
17
return 0; } // end main
Outline
fig22_05.cpp (2 of 2) fig22_05.cpp output (1 of 1)
a and b: true a or b: true not a: false a not_eq b: false a bitand b: 3 a bit_or b: 3 a xor b: 0 compl a: -4 a and_eq b: 3 a or_eq b: 3 a xor_eq b: 1
18
Define function
myFunction( myClass y )
19
Example
First show Array class with implicit conversion Then show Array class with explicit constructor
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// Fig 22.6: array.h // Simple class Array (for integers). #ifndef ARRAY_H #define ARRAY_H #include <iostream> using std::ostream;
20
Outline
array.h (1 of 1)
// class Array definition Without the explicit class Array { this constructor friend ostream &operator<<( ostreamkeyword, &, const Array & ); be used for implicit public: Array( int = 10 ); // default/conversion constructor conversions. ~Array(); // destructor private: int size; // size of the array int *ptr; // pointer to first element of array
}; // end class Array // ARRAY_H
can
#endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// Fig 22.7: array.cpp // Member function definitions for class Array. #include <iostream> using std::cout; using std::ostream; #include <new>
21
Outline
array.cpp (1 of 2)
#include "array.h"
// default constructor for class Array (default size 10) Array::Array( int arraySize ) { size = ( arraySize < 0 ? 10 : arraySize ); cout << "Array constructor called for " << size << " elements\n"; // create space for array ptr = new int[ size ]; // initialize array elements to zeroes for ( int i = 0; i < size; i++ ) ptr[ i ] = 0; } // end constructor
27 28 29 30 31 32 33 34 35 36 37 38 39
22
// destructor for class Array Array::~Array() { delete [] ptr; } // overloaded stream insertion operator for class Array ostream &operator<<( ostream &output, const Array &arrayRef ) { for ( int i = 0; i < arrayRef.size; i++ ) output << arrayRef.ptr[ i ] << ' ' ; return output; } // end operator<< // enables cout << x << y;
Outline
array.cpp (2 of 2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// Fig 22.8: fig22_08.cpp // Driver for simple class Array. #include <iostream> using std::cout; #include "array.h" void outputArray( const Array & ); int main() { Array integers1( 7 ); outputArray( integers1 ); outputArray( 15 ); return 0; } // end main //
23
Outline
fig22_08.cpp (1 of 2)
// convert
Call outputArray and pass output Array integers1 an int . This works because the int is implicitly 15 to an Array and output converted to an Array by the constructor.
22 23 24 25 26 27 28 29
24
// print array contents void outputArray( const Array &arrayToOutput ) { cout << "The array received contains:\n" << arrayToOutput << "\n\n"; } // end outputArray
Outline
fig22_08.cpp (2 of 2) fig22_08.cpp output (1 of 1)
Array constructor called for 7 elements The array received contains: 0 0 0 0 0 0 0 Array constructor called for 15 elements The array received contains: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// Fig. 22.9: array.h // Simple class Array (for integers). #ifndef ARRAY_H #define ARRAY_H #include <iostream> using std::ostream;
25
Outline
array.h (1 of 1)
// class Array definition This time, declare constructor class Array { friend ostream &operator<<( ostream explicit &, const Array & ); . public: explicit Array( int = 10 ); // default constructor ~Array(); // destructor private: int size; // size of the array int *ptr; // pointer to first element of array
}; // end class Array // ARRAY_H
#endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// Fig. 22.10: array.cpp // Member function definitions for class Array. #include <iostream> using std::cout; using std::ostream; #include <new>
26
Outline
array.cpp (1 of 2)
#include "array.h"
// default constructor for class Array (default size 10) Array::Array( int arraySize ) { size = ( arraySize < 0 ? 10 : arraySize ); cout << "Array constructor called for " << size << " elements\n"; // create space for array ptr = new int[ size ]; // initialize array elements to zeroes for ( int i = 0; i < size; i++ ) ptr[ i ] = 0; } // end constructor
27 28 29 30 31 32 33 34 35 36 37 38 39
27
// destructor for class Array Array::~Array() { delete [] ptr; } // overloaded insertion operator for class Array ostream &operator<<( ostream &output, const Array &arrayRef ) { for ( int i = 0; i < arrayRef.size; i++ ) output << arrayRef.ptr[ i ] << ' ' ; return output; } // end operator<< // enables cout << x << y;
Outline
array.cpp (2 of 2)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
// Fig. 22.11: fig22_11.cpp // Driver for simple class Array. #include <iostream> using std::cout; #include "array.h" void outputArray( const Array & ); int main() { Array integers1( 7 ); outputArray( integers1 ); // output Array integers1
28
Outline
fig22_11.cpp (1 of 2)
// ERROR: construction not allowed outputArray( 15 ); // convert 15 to an Array and output outputArray( Array( 15 ) ); // must use constructor return 0; } // end main
26 27 28 29 30 31 32
// display array contents void outputArray( const Array &arrayToOutput ) { cout << "The array received contains:\n" << arrayToOutput << "\n\n"; } // end outputArray
29
Outline
fig22_11.cpp (2 of 2) fig22_11.cpp output (1 of 1)
c:\cpp4e\ch22\FIG22_09_10_11\Fig22_11.cpp(18) : error C2664: 'outputArray' : cannot convert parameter 1 from 'const int' to 'const class Array &' Reason: cannot convert from 'const int' to 'const class Array' No constructor could take the source type, or constructor overload resolution was ambiguous Error executing cl.exe.
30
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// Fig. 21.12: fig21_12.cpp // Demonstrating storage class specifier mutable. #include <iostream> using std::cout; using std::endl;
31
Outline
fig21_12.cpp (1 of 2)
// class TestMutable definition class TestMutable { public: TestMutable( int v = 0 ) { value = v; } void modifyValue() const { value++; } int getValue() const { return value; } private: mutable int value; // mutable member }; // end class TestMutable
27 28 29 30
32
return 0; } // end main
Outline
fig21_12.cpp (2 of 2) fig21_12.cpp output (1 of 1)
33
22.8 Pointers to Class Members (.* and ->*) Use to access class members
Not the same as previously discussed pointers
Class function
void *memPtr ()
Regular function pointer, to function that returns void and takes no arguments
To call function
Need pointer to Test object (tPtr) (tPtr->*memPtr)()
34
22.8 Pointers to Class Members (.* and ->*) Class data member
int *vPtr
Regular pointer to an int
int Test::*vPtr
Pointer to an int member of class Test
To access
Need pointer to object (tPtr) (*tPtr).*vPtr
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// Fig. 22.13 : fig22_13.cpp // Demonstrating operators .* and ->*. #include <iostream> using std::cout; using std::endl; // class Test definition class Test { public: void function() { cout << "function\n"; } int value; // public data member }; // end class Test void arrowStar( Test * ); void dotStar( Test * ); int main() { Test test; test.value = 8; arrowStar( &test ); dotStar( &test ); // assign value 8 // pass address to arrowStar // pass address to dotStar
35
Outline
fig22_13.cpp (1 of 2)
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
36
return 0; } // end main
Outline
fig22_13.cpp (2 of 2)
// access member function of Test object using ->* Assign function pointer to the void arrowStar( Test *testPtr ) { address of function in // declare function pointer Test. Note that neither side void ( Test::*memPtr )() = &Test::function; refers to a specific object. // invoke function indirectly ( testPtr->*memPtr )(); } // end arrowStar
Create // access members of Test object data member using .* pointer to data member value. Then, access the void dotStar( Test *testPtr2 ) { data. int Test::*vPtr = &Test::value; // declare pointer
cout << ( *testPtr2 ).*vPtr << endl; } // end dotStar // access value
function 8
37
Outline
fig22_13.cpp output (1 of 1)
38
Format
Use comma-separated list
class Derived : public Base1, public Base2{ contents }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// Fig. 22.14: base1.h // Definition of class Base1 #ifndef BASE1_H #define BASE1_H
39
Outline
base1.h (1 of 1)
// class Base1 definition class Base1 { There are two base classes in public: this example, each has its own Base1( int parameterValue ) { value = parameterValue; } getData function. int getData() const { return value; } protected: int value; }; // accessible to derived classes // inherited by derived class
#endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// Fig. 22.15: base2.h // Definition of class Base2 #ifndef BASE2_H #define BASE2_H // class Base2 definition class Base2 { public: Base2( char characterData ) { letter = characterData; } char getData() const { return letter; } protected: char letter; }; // accessible to derived classes // inherited by derived class
40
Outline
base2.h (1 of 1)
#endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
// Fig. 22.16: derived.h // Definition of class Derived which inherits // multiple base classes (Base1 and Base2). #ifndef DERIVED_H #define DERIVED_H #include <iostream> using std::ostream; #include "base1.h" #include "base2.h"
41
Outline
derived.h (1 of 1)
// class Derived definition class Derived : public Base1, public Base2 { friend ostream &operator<<( ostream &, const Derived & ); public: Derived( int, char, double ); double getReal() const; private: double real; };
#endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
// Fig. 22.17: derived.cpp // Member function definitions for class Derived #include "derived.h"
42
Outline
Note use of base-class constructors in derived class derived.cpp (1 of 1) constructor.
// constructor for Derived calls constructors for // class Base1 and class Base2. // use member initializers to call base-class constructors Derived::Derived( int integer, char character, double double1 ) : Base1( integer ), Base2( character ), real( double1 ) { } // return real double Derived::getReal() const { return real; } // display all data members of Derived ostream &operator<<( ostream &output, const Derived &derived ) { output << " Integer: " << derived.value << "\n Character: " << derived.letter << "\nReal number: " << derived.real; return output; // enables cascaded calls
// end operator<<
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// Fig. 22.18: fig22_18.cpp // Driver for multiple inheritance example. #include <iostream> using std::cout; using std::endl; #include "base1.h" #include "base2.h" #include "derived.h" int main() { Base1 base1( 10 ), *base1Ptr = 0; // create Base1 object Base2 base2( 'Z' ), *base2Ptr = 0; // create Base2 object Derived derived( 7, 'A', 3.5 ); // create Derived object // print data members of base-class objects cout << "Object base1 contains integer " << base1.getData() << "\nObject base2 contains character " << base2.getData() << "\nObject derived contains:\n" << derived << "\n\n";
43
Outline
fig22_18.cpp (1 of 2)
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
// print data members of derived-class object // scope resolution operator resolves getData ambiguity cout << "Data members of Derived can be" << " accessed individually:" << "\n Integer: " << derived.Base1::getData() << "\n Character: " << derived.Base2::getData() << "\nReal number: " << derived.getReal() << "\n\n"; cout << "Derived can be treated as an " << "object of either base class:\n"; // treat Derived as a Base1 object base1Ptr = &derived; cout << "base1Ptr->getData() yields " << base1Ptr->getData() << '\n'; // treat Derived as a Base2 object base2Ptr = &derived; cout << "base2Ptr->getData() yields " << base2Ptr->getData() << endl; return 0; } // end main
44
Outline
fig22_18.cpp (2 of 2)
Object base1 contains integer 10 Object base2 contains character Z Object derived contains: Integer: 7 Character: A Real number: 3.5 Data members Integer: Character: Real number: of Derived can be accessed individually: 7 A 3.5
45
Outline
fig22_18.cpp output (1 of 1)
Derived can be treated as an object of either base class: base1Ptr->getData() yields 7 base2Ptr->getData() yields A
46
22.10 Multiple Inheritance and virtual Base Classes Ambiguities from multiple inheritance
ios istream iostream ostream
47
22.10 Multiple Inheritance and virtual Base Classes Solution: use virtual base class inheritance
Only one subobject inherited into multiply derived class
Base Class virtual inheritance First Derived Class
virtual inheritance
Multiply-Derived Class
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
// Fig. 22.20: fig22_20.cpp // Attempting to polymorphically call a function that is // multiply inherited from two base classes. #include <iostream> using std::cout; using std::endl;
48
Outline
fig22_20.cpp (1 of 3)
// class Base definition class Base { public: virtual void print() const = 0; }; // end class Base
// class DerivedOne definition class DerivedOne : public Base { public: // override print function void print() const { cout << "DerivedOne\n"; }
};
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
// class DerivedTwo definition class DerivedTwo : public Base { public: // override print function void print() const { cout << "DerivedTwo\n"; } }; // end class DerivedTwo
49
Outline
fig22_20.cpp (2 of 3)
// class Multiple definition class Multiple : public DerivedOne, public DerivedTwo { public:
// qualify which version of function print void print() const { DerivedTwo::print(); } }; // end class Multiple
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
50
Outline
// instantiate Multiple object // instantiate DerivedOne object // instantiate DerivedTwo object
fig22_20.cpp (3 of 3)
used?
// ERROR--ambiguous
// polymorphically invoke print for ( int i = 0; i < 3; i++ ) array[ i ] -> print(); return 0; } // end main
c:\cpp4e\ch22\fig22_20_21\fig22_20.cpp(52) : error C2594: '=' : ambiguous conversions from 'class Multiple *' to 'class Base *' Error executing cl.exe. test.exe - 1 error(s), 0 warning(s)
51
Outline
fig22_20.cpp output (1 of 1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// Fig. 22.21: fig22_21.cpp // Using virtual base classes. #include <iostream> using std::cout; using std::endl; // class Base definition class Base { public: // implicit default constructor virtual void print() const = 0; // pure virtual }; // end Base class
52
Outline
fig22_21.cpp (1 of 3)
// class DerivedOne definition class DerivedOne : virtual public Base { public: // implicit default constructor calls // Base default constructor
// override print function void print() const { cout << "DerivedOne\n"; } }; // end DerivedOne class
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
53
// class DerivedTwo definition class DerivedTwo : virtual public Base { public: // implicit default constructor calls // Base default constructor
Outline
fig22_21.cpp (2 of 3)
// override print function void print() const { cout << "DerivedTwo\n"; } }; // end DerivedTwo class // class Multiple definition class Multiple : public DerivedOne, public DerivedTwo { public: // implicit default constructor calls // DerivedOne and DerivedTwo default constructors // qualify which version of function print void print() const { DerivedTwo::print(); } }; // end Multiple class
53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
54
int main() { Multiple both; DerivedOne one; DerivedTwo two;
Outline
// instantiate Multiple object // instantiate DerivedOne object // instantiate DerivedTwo object
fig22_21.cpp (3 of 3)
// declare array of base-class pointers and initialize // each element to a derived-class type Base *array[ 3 ]; array[ 0 ] = &both; array[ 1 ] = &one; array[ 2 ] = &two; // polymorphically invoke function print for ( int i = 0; i < 3; i++ ) array[ i ]->print(); return 0; } // end main
55
Outline
fig22_21.cpp output (1 of 1)