<< "  Total Worth: $" << this->total_val << '\n';

}

That is, it converted a Stock:: qualifier to a function argument that is a pointer to Stock and then uses the pointer to access class members.

Similarly, the front end converted function calls like

top.show();

to this:

show(⊤);

In this fashion, the this pointer is assigned the address of the invoking object. (The actual details might be more involved.)

Class Scope

Chapter 9 discusses global (or file) scope and local (or block) scope. Recall that you can use a variable with global scope anywhere in the file that contains its definition, whereas a variable with local scope is local to the block that contains its definition. Function names, too, can have global scope, but they never have local scope. C++ classes introduce a new kind of scope: class scope.

Class scope applies to names defined in a class, such as the names of class data members and class member functions. Items that have class scope are known within the class but not outside the class. Thus, you can use the same class member names in different classes without conflict. For example, the shares member of the Stock class is distinct from the shares member of a JobRide class. Also class scope means you can’t directly access members of a class from the outside world. This is true even for public function members. That is, to invoke a public member function, you have to use an object:

Stock sleeper("Exclusive Ore", 100, 0.25);  // create object

sleeper.show();      // use object to invoke a member function

show();              // invalid -- can't call method directly

Similarly, you have to use the scope-resolution operator when you define member functions:

void Stock::update(double price)

{

    ...

}

In short, within a class declaration or a member function definition you can use an unadorned member name (the unqualified name), as when sell() calls the set_tot() member function. A constructor name is recognized when it is called because its name is the same as the class name. Otherwise, you must use the direct membership operator (.), the indirect membership operator (->), or the scope-resolution operator (::), depending on the context, when you use a class member name. The following code fragment illustrates how identifiers with class scope can be accessed:

class Ik

{

private:

   int fuss;       // fuss has class scope

public:

   Ik(int f  = 9) {fuss = f; }  // fuss is in scope

   void ViewIk() const;         // ViewIk has class scope

};

void Ik::ViewIk() const    //Ik:: places ViewIk into Ik scope

{

   cout << fuss << endl;   // fuss in scope within class methods

}

...

int main()

{

   Ik * pik = new Ik;

   Ik ee = Ik(8); // constructor in scope because has class name

   ee.ViewIk();   // class object brings ViewIk into scope

   pik->ViewIk(); // pointer-to-Ik brings ViewIk into scope

...

Class Scope Constants

Sometimes it would be nice to have symbolic constants with class scope. For example, a class declaration might use the literal 30 to specify an array size. Because the constant is the same for all objects, it would be nice to create a single constant shared by all objects. You might think the following would be a solution:

class Bakery

{

private:

    const int Months = 12;    // declare a constant? FAILS

    double costs[Months];

    ...

But this won’t work because declaring a class describes what an object looks like but doesn’t create an object. Hence, until you create an object, there’s no place to store a value. (Actually, C++11 provides for member initialization, but not in a way that would make the preceding array declaration work; Chapter 12 returns to this topic.) There are, however, a couple ways to achieve essentially the same desired effect.

First, you can declare an enumeration within a class. An enumeration given in a class declaration has class scope, so you can use enumerations to provide class scope symbolic names for integer constants. That is, you can start off the Bakery declaration this way:

class Bakery

{

private:

    enum {Months = 12};

    double costs[Months];

    ...

Note that declaring an enumeration in this fashion does not create a class data member. That is, each individual object does not carry an enumeration in it. Rather, Len is just a symbolic name that the compiler replaces with 30 when it encounters it in code in class scope.

Because the Bakery class uses the enumeration merely to create a symbolic constant, with no intent of creating variables of the enumeration type, you needn’t provide an enumeration tag. Incidentally, for many implementations, the ios_base class does something similar in its public section; that’s the source of identifiers such as ios_base::fixed. Here fixed is typically an enumerator defined in the ios_base class.

C++ has a second way of defining a constant within a class—using the keyword static:

class Bakery

{

private:

    static const int Months = 12;

    double costs[Months];

    ...

Перейти на страницу:

Все книги серии Developer's Library

Похожие книги