Implementing Scalar Properties


As mentioned in the previous section, a scalar property is one that gives you access to a single data member using the get and set methods. The following exercise shows you how to implement scalar properties on a managed class, using a simple Person class containing name and age members.

  1. Start Microsoft Visual Studio .NET, and open a new Visual C++ Console Application (.NET) project named Person.

  2. Add the following class definition after using namespace System; and before the _tmain function:

    __gc class Person { String* name; int age; public: // Person class constructors Person() { name = 0; age = 0; } // The Name property __property String* get_Name() { return name; } __property void set_Name(String* s) { name = s; } // The Age property __property int get_Age() { return age; } __property void set_Age(int n) { age = n; } };

    The class has two private data members that hold the name and age of the person. Properties are implemented using the get and set methods, and you tell the compiler that these are property methods (as opposed to some other methods that just happen to start with get_ and set_) using the __property keyword.

    The compiler uses the part of the name after get_ or set_ to generate the virtual data member that clients will use. In the preceding code, get_Name and set_Name will result in the class getting a virtual data member named Name.

    Note

    You can’t use get_name and set_name as the names of your property methods because doing so would result in a virtual member named name, which would clash with the existing real data member named name. However, it’s common to use the name of an existing data member with different case as the name of a property.

  3. You can use the property from C++ code as if it were a real data member of the class. Add the following code to _tmain to test the property:

    int _tmain() { // Create a Person object Person* pp = new Person(); // Set the name and age using properties pp->Name = "fred"; pp->Age = 77; // Access the properties Console::WriteLine(S"Age of {0} is {1}", pp->Name, __box(pp->Age)); return 0; }

    Once a Person object has been created and initialized, the name and age members can be accessed through the Name and Age virtual data members that have been generated by the compiler.

Errors in Properties

What happens if a property get or set method encounters an error? Consider the following code:

// Set the name and age using properties pp->Name = "spiro"; pp->Age = -31;

This situation is a good one in which to use exceptions, which were discussed in Chapter 11. The property set method needs to communicate that the value passed in isn’t acceptable, and exceptions provide the best way to do this. You could modify the set_Age function to check its argument like this:

__property void set_Age(int n) { if (n < 0) throw new ArgumentException("Negative ages aren’t allowed"); age = n; }

If anyone tries to set the age to a negative value, an ArgumentException that has to be caught in the calling code will be thrown.

start sidebar
Rules for Constructing Scalar Properties

A number of rules govern how scalar properties are created in managed C++. First, all properties must be declared using the __property keyword. Properties are implemented using the get and set methods, and any method whose name starts with get_ or set_ must define a property get or set method.

The names of the get and set methods must be the same except for the prefix, and as you’ve already seen, you can’t use a name that resolves to the same name as another member of the class. The access level to get and set methods can be different, so a class can have a public get method and a protected set method, for example.

Properties can be virtual and even pure virtual, and it isn’t necessary for both the get and set methods to have the same virtual specifier.

end sidebar

Read-Only and Write-Only Properties

You don’t always have to provide get and set methods for a property. If you don’t provide a set method, you end up with a read-only property. If you omit the get method, you’ll have a write-only property (which is possible, but a lot less common than the read-only variety).

This exercise shows how to implement a read-only property, and it also illustrates how to create a derived property. You’ll change the Person class from the previous exercise so that it includes a date of birth rather than an age. The derived Age property will then calculate the person’s age from the date of birth; it’s obviously a derived property because you can’t change someone’s age without changing his or her date of birth as well. It’s also obviously a read-only property because it’s always calculated and cannot be set by users of the class.

  1. Either start a new Visual C++ Console Application (.NET) project, or modify the one from the previous exercise.

  2. Enter or edit the definition of the Person class so that it looks like the following code. Place it after using namespace System; and before the _tmain method:

    __gc class Person { String* name; int dd, mm, yyyy; public: // Person class constructors Person() { name = 0; dd = 0; mm = 0; yyyy = 0; } Person(String* n, int d, int m, int y) { name = n; dd = d; mm = m; yyyy = y; } // The Name property __property String* get_Name() { return name; } __property void set_Name(String* s) { name = s; } // The read-only Age property __property int get_Age() { DateTime now = DateTime::get_Now(); return now.get_Year() - yyyy; } };

    The class now has four data members: a String for the name and three integers to hold the date of birth. A second constructor for the class is used to create an object with the date of birth set from the arguments.

Note

It would be neater to use a System::DateTime object to represent the date of birth, but you can’t have pointers to managed types as members of a __gc class.

The Age property now has only a get method, which retrieves a DateTime object representing the current date and time and then calculates the age from the difference between the current year and the stored year.

  1. Use the Name and Age properties as you did in the previous example:

    int _tmain() { // Create a Person object Person* pp = new Person("fred", 4,9,1955); // Access the Name and Age properties Console::WriteLine(S"Age of {0} is {1}", pp->Name, __box(pp->Age)); return 0; }

    You can’t set the Age property because you haven’t provided a set_Age function, and you’ll get a compiler error if you try to assign to the Age property.




Microsoft Visual C++  .NET(c) Step by Step
Microsoft Visual C++ .NET(c) Step by Step
ISBN: 735615675
EAN: N/A
Year: 2003
Pages: 208

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net