TweetFollow Us on Twitter

C++ Basics
Volume Number:9
Issue Number:10
Column Tag:Getting Started

C++ Basics

What does “::” mean anyway?

By Dave Mark, MacTech Magazine Regular Contributing Author

So far, this column has focused on Macintosh programming, with an emphasis on C. This month, we’re going to switch gears and talk about C++. With Addison-Wesley’s permission, I’ve codged together some bits and pieces from Learn C++ on the Macintosh that I thought might interest you. Unfortunately, there’s no way to cover all of C++ in a single column. If you would like to hear more about C++, send your comments and suggestions to Neil at any one of the editorial addresses on page 2 of this issue.

And now, some legal mumbo jumbo... Portions of this article were derived from Learn C++ on the Macintosh, ©1993, by Dave Mark, published by Addison-Wesley Publishing Co. And now back to our regularly scheduled program...

For the past few years, Apple (along with a host of other companies) has shifted away from procedural languages such as C and Pascal and made C++ their primary developmental language.

Why C++?

C++ is a superset of C and offers all the advantages of a procedural language. You can write a C++ program filled with for loops and if statements just as you would in C. But C++ offers much, much more. C++ allows you to create objects. An object is sort of like a struct on steroids. Understanding the value of objects is the key to understanding the popularity of C++.

Understanding Object Programming

As its name implies, an object programming language allows you to create, interact with, and delete objects. Just as a variable is based on a type definition, an object is based on a class definition. First, you’ll declare a class, then you’ll define an object (or many objects) said to be members of that class. While a struct definition is limited to data elements only, a class definition can include both data elements (called data members) as well as function pointers (called member functions). To make this clearer, let’s start with a simple problem and see how we’d solve it using both structs and objects.

Our First Example

Suppose you wanted to implement an employee data base that tracked an employee’s name, employee ID, and salary. You might design a struct that looks like this:

/* 1 */
const short kMaxNameSize = 20;

struct Employee
{
 char   name[ kMaxNameSize ];
 long   id;
 float  salary;
};

You may have noticed the use of const instead of a #define. Believe it or not, const is part of the ANSI C standard and is not just found in C++. Though many C programmers prefer to use #defines to define a constant, C++ programmers always use const. The major advantage of using const is that a typed constant is created. If you pass a const as a parameter to a function, for example, C++’s parameter checking will ensure that you are passing a constant of the correct type. A #define just does a simple text substitution during the first pass of the compiler.

The great advantage of the struct declared above is that it lets you bundle several pieces of information together under a single name. For example, if you wrote a routine to print an employee’s data, you could write:

/* 2 */

struct Employee  newHire;
 •
 •
 •
PrintEmployee( newHire.name, newHire.id, newHire.salary );

On the other hand, it is more convenient to pass the data in its bundled form:

/* 3 */
PrintEmployee( &newHire );

Bundling allows you to represent complex information in a more natural, easily accessible form. In the C language, the struct is the most sophisticated bundling mechanism available. As you'll soon see, C++ takes bundling to a new level.

When you write your employee management program using structs, you’ll naturally develop a series of functions to access and modify the fields in your various Employee structs. You’ll also develop some functions that manage and organize the structs themselves (i.e., linked list functions). Though this might be a subtle point, it’s important to note that these functions are in no way connected to the Employee structs. Most likely, each function will take a pointer to an Employee as a parameter, but that’s as far as the bundling gets.

Why bundle the functions with the data? Here’s one reason. Think about all the data that you want to be available to all of your Employee structs (a pointer to the head of your Employee linked list, for example). In C, you’d most likely declare these variables as globals, storing them with a bunch of other globals that have nothing to do with the Employee structs. Wouldn’t it be nice if you could bundle Employee linked list globals with the functions that manage your Employee linked lists. Then, you could bundle all your other globals with the functions that they belong with.

C does offer one mechanism to do this. You can define the appropriate globals in the same file with their related functions. This can work pretty well and is the best you can do in C. The trouble comes when you want to reference the global outside the file it is declared in (there’s always some exception) or if you’ve defined a function that needs to refer to globals from two different categories.

The point here is that C doesn’t naturally offer a mechanism that allows you to bundle functions and data. C++ does.

Bundling Data and Functions

Just as C bundles data together in a struct declaration, C++ bundles data and functions together in a class declaration. Here’s an example:

/* 4 */

const short kMaxNameSize = 20;

class Employee
{
// Data members...
 char   employeeName[ kMaxNameSize ];
 long   employeeID;
 float  employeeSalary;

// Member functions...
 void   PrintEmployee( void );
};

A class declaration is similar in form to a struct declaration. Notice that the keyword struct has been replaced by the keyword class. This example declares a class with the name Employee. The Employee class bundles together three data fields as well as a function named PrintEmployee(). As mentioned earlier, a classes’ data fields are known as data members and a classes’ functions are known as member functions.

Just as you’d use a struct declaration to define a struct variable, you’ll use your class declaration to define a variable known as an object.

It’s useful to be aware of the difference between a definition and a declaration. For a variable, the definition is the statement that actually allocates memory. For example, the statement:

short myShort;

is a definition. On the other hand, an extern reference to the same variable:

extern short myShort;

is a declaration, since this statement doesn’t cause any memory to be allocated. Here’s another example of a declaration:

typedef MyType short;

For a function, the function prototype is a declaration and the function implementation, complete with function code, is a definition.

When you define a struct variable, you allocate a block of memory big enough to hold all the struct’s fields. When you define an object, you allocate a block of memory big enough to hold the object’s data members. In addition to the data members, the compiler will also make sure that your object also has access to pointers to all of the functions belonging to its class.

Creating an Object

There are two ways to create a new object. The simplest method is to define the object directly, just as you would a regular variable:

Employeeemployee1;

This definition creates an object named employee1 belonging to the Employee class. Figure 1 shows this definition, seen from a memory perspective. employee1 consists of a block of memory large enough to accomodate each of the three Employee data members, as well as a pointer to the single Employee function, PrintEmployee().

Figure 1. An Employee object, created by definition.

Note that the function pointer probably won’t be stored in the object itself. I’m just trying to show that the new object has access to the PrintEmployee() function.

When you create an object by definition, as we did above, memory for the object is allocated, automatically, when the definition moves into scope. That same memory is freed up when the object drops out of scope.

For example, you might define an object at the beginning of a function:

/* 5 */

void CreateEmployee( void )
{
 Employee employee1;

 •
 •
 •
}

When the function is called, memory for the object is allocated, right along with the function’s other local variables. When the function exits, the object’s memory is deallocated.

[definition] Objects created by definition are known as automatic objects, because memory for them is allocated and deallocated automatically.

Although automatic objects are simple to create, they do have a downside. Once they drop out of scope, they cease to exist. If you want your object to outlive its scope, take advantage of C++’s new operator.

new is a lot like malloc() or the Toolbox call NewPtr(), though the syntax is a bit different. new takes a type instead of a number of bytes. Also, new (and its partner delete) is a built-in C++ operator, as opposed to a special library function.

First, define an object pointer, then call new to allocate the memory for your object. new returns a pointer to the newly created object. Here’s some code that creates an Employee object:

/* 6 */

Employee*employeePtr;

employeePtr = new Employee;

The first line of code defines a pointer designed to point to an Employee object. The second line uses new to create an Employee object. new returns a pointer to the newly created Employee.

Figure 2 shows what this looks like from a memory perspective. employeePtr is a pointer, pointing to an object of the Employee class. As was the case previously, the Employee object consists of a block of memory large enough to accomodate each of the three Employee data members, as well as a pointer to the single Employee function, PrintEmployee().

Figure 2 An object pointer, pointing to an object, pointing to some code.

Once again, this picture may not reflect the reality of your C++ compiler. The function pointer may not be stored with the object itself.

Suppose we create a second Employee object:

/* 7 */

Employee*employee1Ptr, *employee2Ptr;

employee1Ptr = new Employee;
employee2Ptr = new Employee;

Take a look at Figure 3. Notice that the second Employee object gets its own block of memory, with its very own copy of the Employee data members and its own function pointer. Notice also that both objects point to the same copy of PrintEmployee() in memory. Every single Employee object gets its own copy of the Employee data members. At the same time, all Employee objects share a single copy of the Employee member functions.

Figure 3. A second Employee, pointing to the same code.

Accessing an Object’s Data Members and Member Functions

Once you’ve created an object, you can call its functions and modify its data members. Remember, each object you create has its own copy of the data members defined by its class. You’ll refer to an object’s data members and member functions in much the same way as you’d refer to the fields of a struct. If you’ve defined the object directly, use the . operator:

/* 8 */

Employeeemployee1;

employee1.employeeSalary = 200.0;

If you’re working with an object pointer, use the -> operator:

/* 9 */

Employee*employeePtr;

employeePtr = new Employee;

employeePtr->employeeSalary = 200.0;

To call a member function, use the same technique. If the object was created automatically, you’ll use the . operator:

/* 10 */

Employeeemployee1;

employee1.PrintEmployee();

If the object was created using new, you’ll use the -> operator:

/* 11 */

Employee*employeePtr;

employeePtr = new Employee;

employeePtr->PrintEmployee();

The Current Object

In the previous examples, each reference to a data member or member function started with an object or object pointer. When you are inside a member function, however, the object or object pointer isn’t necessary.

For example, inside the PrintEmployee() function, you can refer to the data member employeeSalary directly, without referring to an object or object pointer:

/* 12 */

if ( employeeSalary <= 200 )
 cout << "Give this person a raise!!!";

This code is kind of puzzling. What object does employeeSalary belong to? After all, you’re used to saying:

myObject->employeeSalary

instead of just plain:

employeeSalary

The key to this puzzle lies in knowing which object spawned the call of PrintEmployee() in the first place. Although this may not be obvious, a call to a member function must originate with a single object.

Suppose you called PrintEmployee() from a non-Employee function (such as main()). You must start this call off with a reference to an object:

employeePtr->PrintEmployee();

Whenever a class function is called, C++ keeps track of the object used to call the function. This object is known as the current object.

In the call of PrintEmployee() above, the object pointed to by employeePtr is the current object. Whenever this call of PrintEmployee() refers to an Employee data member or function without using an object reference, the current object (in this case, the object pointed to by employeePtr) is assumed.

Suppose PrintEmployee() then called another Employee function. The object pointed to by employeePtr is still considered the current object. A reference to employeeSalary would still modify the current object’s copy of employeeSalary.

The point to remember is, a member function always starts up with a single object in mind. This object, which we’ve called the current object, is always of the same class as the function.

The “This” Alternative

In the pursuit of legibile code, C++ provides a generic object pointer, available inside any member function, that points to the current object. The generic pointer has the name “this”. For example, inside every Employee function, the line:

this->employeeSalary = 400;

is equivalent to this line:

employeeSalary = 400;

You don’t have to use this, but it does make the code a little easier to read. If you refer to a data member or function using this, it is quite clear that the data member or function is part of the class, and not a local or global variable.

[By the way] Another benefit of this occurs when you declare a local variable with the exact same name as a data member. For example, suppose PrintEmployee() declared a local variable (or had a parameter) named employeeSalary. When employeeSalary comes up in the code, which does it refer to, the local or the data member? As it turns out, the local variable (or parameter) wins out in case of a conflict, but you can avoid the conflict altogether by either using this or by naming your variables more carefully.

Deleting an Object

As we mentioned earlier, objects created by definition are created and deleted automatically. For example, suppose the Employee function PrintEmployee() defined its own Employee object, right at the beginning of the function:

EmployeelocalEmployee;

localEmployee is created, automatically, at the beginning of PrintEmployee(), and is deleted as soon as PrintEmployee() exits.

Non-automatic objects are another story altogether. If you create an object with new, you’ll delete the object yourself by using the delete operator. Here’s the syntax:

/* 13 */

Employee*employeePtr;

employeePtr = new Employee;

delete employeePtr;

As you’d expect, delete deletes the specified object, freeing up any memory allocated for the object. Note that this freed up memory only includes memory for the actual object and does not include any extra memory you may have allocated. You’ll have to free up that memory yourself.

Writing Class Functions

Once your class is defined, you’re ready to write your classes’ member functions. Member functions behave in much the same way as ordinary functions, with a few small differences. One difference, pointed out earlier, is that a member function automatically has access to the data members and functions of the object that called it.

Another difference lies in the function implementation’s title line. Here’s a sample:

/* 14 */

void  Employee::PrintEmployee( void )
{
 cout << "Employee Name:   " << employeeName << "\n";
}

Notice that the function name is preceded by the class name and two colons. This notation is mandatory and tells the compiler that this function is a member of the specified class.

The Constructor Function

Typically, when you create an object, you’ll want to perform some sort of initialization on the object. For example, you might want to provide initial values for your object’s data members. The constructor function is C++’s built-in initialization mechanism.

The constructor function (or just plain constructor) is a member function that has the same name as the class. For example, the constructor for the Employee class is named Employee(). When an object is created, the constructor for that class gets called, automatically.

Consider this code:

/* 15 */

Employee*employeePtr;

employeePtr = new Employee;

In the second line, the new operator allocates a new Employee object, then immediately calls the object’s constructor. Once the constructor returns, a pointer to the new object is assigned to employeePtr.

This same scenario holds true for an automatic object:

Employeeemployee1;

As soon as the object is created, its constructor is called.

Here’s our Employee class declaration with the constructor declaration added in:

/* 16 */

const short kMaxNameSize = 20;

class Employee
{
// Data members...
 char   employeeName[ kMaxNameSize ];
 long   employeeID;
 float  employeeSalary;

// Member functions...
 Employee( void );
 void   PrintEmployee( void );
};

Notice that the constructor is declared without a return value. Constructors never return a value. This being the case, you won’t want to call any functions that do return a value inside your constructor. As an example, it’s not a good idea to allocate memory inside your constructor.

[definition] In general, an object’s constructor will initialize each of the object’s data members. The constructor will not make any calls that return a status, or that can fail. As your objects get more complex, you’ll want to move to two-stage construction.

With two-stage construction, you create an additional member function that you call after the constructor returns. Typically, this second routine takes the name I, followed by the class name. For example, the second-stage constructor for the Employee class would be named IEmployee().

This example creates an Employee object using two-stage construction:

/* 17 */

Employee*employeePtr;
short   objectStatus;

employeePtr = new Employee();

objectStatus = employeePtr->IEmployee();

Since IEmployee() can return a status, this is the perfect place to allocate memory, or perform any other initialization that has the potential of failing.

Here’s a sample constructor:

/* 18 */
Employee::Employee( void )
{
 employeeSalary = 200.0;
}

As mentioned earlier, the constructor is declared without a return value. This is proper form.

[By the way] Constructors are optional. If you don’t have any initialization to perform, don’t define one. When an object is created, the constructor is only called if it is included in the class declaration.

Adding Parameters to Your Constructor

If you like, you can add parameters to your constructor. Constructor parameters are typically used to provide initial values for the object’s data members. Here’s a new version of the Employee() constructor:

/* 19 */

Employee::Employee( char *name, long id, float salary )
{
 strcpy( employeeName, name );
 employeeID = id;
 employeeSalary = salary;
}

The constructor copies the three parameter values into the corresponding data members. The object that was just created is always the constructor’s current object. In other words, when the constructor refers to an Employee data member, such as employeeName or employeeSalary, it is referring to the copy of that data member in the newly created object.

Notice that this constructor used different names for a parameter and its corresponding data member. Some programmers prefer to use the same name, using this to keep things straight:

/* 20 */

Employee::Employee( char *employeeName, long employeeID, 
 float employeeSalary )
{
 strcpy( this->employeeName, employeeName );
 this->employeeID = employeeID;
 this->employeeSalary = employeeSalary;
}

As you write your own code, pick a style you feel comfortable with and be consistent.

This line of code supplies the new operator with a set of parameters to pass on to the constructor:

employeePtr = new Employee( "Dave Mark", 1000, 200.0 );

[By the way] Notice that the parameter list was appended to the class name, making it look just like a function call. Don’t be fooled! This line of code specifies the parameters to be passed to the new object’s constructor function. It does not call the constructor directly. The constructor call happens behind the scenes and no return value is generated. Thought you’d like to know...

This line of code creates an automatic object using parameters:

Employeeemployee1( "Dave Mark", 1000, 200.0 );

As you might expect, this code creates an object named employee1, then calls the Employee constructor, passing it the three specified parameters.

Just for completeness, here’s the class declaration again, showing the new, paramaterized constructor:

/* 21 */

class Employee
{
// Data members...
 char   employeeName[ kMaxNameSize ];
 long   employeeID;
 float  employeeSalary;

// Member functions...
 Employee( char *name, long id, float salary );
 void   PrintEmployee( void );
};

The Destructor Function

The destructor function is called automatically, just like the constructor. Unlike the constructor, however, the destructor is called when an object in its class is deleted. Use the destructor to clean up after your object before it goes away. For instance, you might use the destructor to deallocate any additional memory your object may have allocated.

The destructor function is named by a tilda character (~) followed by the class name. The destructor for the Employee class is named ~Employee(). The destructor has no return value and no parameters.

Here’s a sample destructor:

/* 22 */

Employee::~Employee( void )
{
 cout << "Deleting employee #" << employeeID << "\n";
}

If you created your object using new, the destructor is called when you call delete:

/* */
Employee*employeePtr;

employeePtr = new Employee;

delete employeePtr;

If your object was created automatically, the destructor is called just before the object is deleted. For example, if the object was declared at the beginning of a function, the destructor is called when the function exits.

[By the way] If your object was defined as a global variable, its constructor will be called at the beginning of the program and its destructor will be called just before the program exits. Yes, global objects are automatic and have scope, just like local objects.

Here’s an updated Employee class declaration showing the constructor and destructor:

/* 23 */

class Employee
{
// Data members...
 char   employeeName[ kMaxNameSize ];
 long   employeeID;
 float  employeeSalary;

// Member functions...
 Employee( char *name, long id, float salary );
 ~Employee( void );
 void   PrintEmployee( void );
};

[By the way] If you use two-stage initialization, check the return status of your extra initializer right away. If your request for additional memory fails, for example, you might want to delete the object you just created.

/* 24 */

Employee*employeePtr;

employeePtr = new Employee();

if ( employeePtr->IEmployee() == false )
 delete employeePtr;

Whether you use two-stage initialization or not, it’s a good idea to keep your constructor and destructor in sync. If you allocated extra memory, be sure your destructor has some way of knowing about it. For example, it’s good practice to initialize your pointers to null. If your destructor encounters a non-null pointer, it knows that additional memory has been allocated that must be deallocated.

Till Next Month...

Obviously, we’ve just touched on the surface of C++. If you are interested in learning more about C++, there are a lot of good books out there. In addition to Learn C++ on the Macintosh (by yours truly), check out the C++ Primer, second edition, by Stanley Lippman and the C++ Programming Language, second edition, by the man who created C++, Bjarne Stroustrup. In my opinion, these two books belong on every C++ programmers bookshelf.

Next month, I think we’ll dive back into the Macintosh Toolbox. See you then...

[Dave Mark is too humble to comment on his own books, but I can. All of his books are some of the best selling books that Addison-Wesley publishes for the Macintosh (outside of Inside Macintosh). If one of his books covers a topics that fits your needs - buy it! These books are available at most large bookstores and through the MacTech Mail Order Store at a discount. - Ed.]

 
AAPL
$100.41
Apple Inc.
-0.17
MSFT
$45.11
Microsoft Corpora
+0.16
GOOG
$583.46
Google Inc.
-1.03

MacTech Search:
Community Search:

Software Updates via MacUpdate

Videobox 4.1.1 - Download Flash video th...
Videobox allows you to quickly and easily download Flash video from most all of the popular video sites on the internet. Videobox will convert the video into a native Quicktime format so it's ready... Read more
Web Snapper 3.3.5 - Capture entire Web p...
Web Snapper lets you capture Web pages exactly as they appear in your browser. You can send them to a file as images or vector-based, multi-page PDFs. It captures the whole Web page - eliminating... Read more
Picasa 3.9.138 - Organize, edit, and sha...
Picasa and Picasa Web Albums allows you to organize, edit, and upload your photos to the Web from your computer in quick, simple steps. Arrange your photos into folders and albums and erase their... Read more
Tidy Up 3.0.15.0 - Find duplicate files...
Tidy Up is a complete duplicate finder and disk-tidiness utility. With Tidy Up you can search for duplicate files and packages by the owner application, content, type, creator, extension, time... Read more
Parallels Desktop 10.0 - Run Windows app...
Parallels Desktop is simply the world's bestselling, top-rated, and most trusted solution for running Windows applications on your Mac. With Parallels Desktop for Mac, you can seamlessly run both... Read more
Apple Final Cut Pro X 10.1.3 - Professio...
Apple Final Cut Pro X is a professional video editing solution.Completely redesigned from the ground up, Final Cut Pro adds extraordinary speed, quality, and flexibility to every part of the post-... Read more
Apple Compressor 4.1.3 - Adds power and...
Compressor adds power and flexibility to Final Cut Pro X export. Customize output settings, work faster with distributed encoding, and tap into a comprehensive set of delivery features. Powerful... Read more
Chromium 36.0.1985.143 - Fast and stable...
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all Internet users to experience the web. FreeSMUG-Free OpenSource Mac User Group build is... Read more
Macgo Blu-ray Player 2.10.6.1691 - Blu-r...
Macgo Mac Blu-ray Player can bring you the most unforgettable Blu-ray experience on your Mac. Overview Macgo Mac Blu-ray Player can satisfy just about every need you could possibly have in a Blu-ray... Read more
Apple Motion 5.1.2 - Create and customiz...
Apple Motion is designed for video editors, Motion 5 lets you customize Final Cut Pro titles, transitions, and effects. Or create your own dazzling animations in 2D or 3D space, with real-time... Read more

Latest Forum Discussions

See All

BoxPop Review
BoxPop Review By Jennifer Allen on August 21st, 2014 Our Rating: :: UNTAXING PUZZLESUniversal App - Designed for iPhone and iPad Move from tile to tile to clear the board in this slightly too simple and easy puzzle game.   | Read more »
Breakdown Buddy Review
Breakdown Buddy Review By Jennifer Allen on August 21st, 2014 Our Rating: :: FLAWED CONCEPTiPhone App - Designed for the iPhone, compatible with the iPad There’s a good idea here, but Breakdown Buddy isn’t as useful as it tries to... | Read more »
jamstik, the Guitar You Can Take Everywh...
jamstik, the Guitar You Can Take Everywhere, is Now Available for Purchase Posted by Jessica Fisher on August 21st, 2014 [ permalink ] Zivix has announced that their guitar-in-your-pocket, | Read more »
Star Walk 2 - Guide to the Sky Day and N...
Star Walk 2 - Guide to the Sky Day and Night 1.0.0 Device: iOS Universal Category: Education Price: $2.99, Version: 1.0.0 (iTunes) Description: The next generation of the best-selling Star Walk, winner of Apple Design Award, used by... | Read more »
Forks Over Knives Review
Forks Over Knives Review By Jennifer Allen on August 21st, 2014 Our Rating: :: TASTY AND HEALTHYUniversal App - Designed for iPhone and iPad Want some tasty new recipe ideas but want to keep it healthy? Forks Over Knives is the... | Read more »
Invaders! From Outer Space (Games)
Invaders! From Outer Space 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: | Read more »
Dementia: Book of the Dead (Games)
Dementia: Book of the Dead 1.00 Device: iOS Universal Category: Games Price: $2.99, Version: 1.00 (iTunes) Description: EXCLUSIVE CONTENT ONLY ON THE APP STORE. Medieval England. Times of knights, witches and hunters. What other... | Read more »
Wan Nyan Slash (Games)
Wan Nyan Slash 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: Wan Nyan Slash is an infinite adorable demon slaying slashing action game! Play as the wandering samurai Wan and Nyan as they... | Read more »
Fallin Love - The Game of Love (Games)
Fallin Love - The Game of Love 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: GRAVITATE AROUND LOVE | Read more »
Ancient Battle: Hannibal (Games)
Ancient Battle: Hannibal 1.0 Device: iOS Universal Category: Games Price: $.99, Version: 1.0 (iTunes) Description: | Read more »

Price Scanner via MacPrices.net

21-inch iMacs on sale for up to $150 off MSRP
B&H Photo has 21″ iMacs on sale for up to $150 off MSRP including free shipping plus NY sales tax only. B&H will also include a free copy of Parallels Desktop software: - 21″ 2.7GHz iMac: $... Read more
27-inch 3.2GHz iMac on sale for $1698, save $...
Abt has the 27″ 3.2GHz iMac on sale for $1698 including free shipping. Their price is $101 off MSRP. Read more
Mac Backup Guru 2.0 Drive Backup/Cloneing Uti...
Mac Backup Guru developer MacDaddy has released Mac Backup Guru 2.0, offering new and enhanced advanced features, such as bootable backups, synchronised volumes and folders, and a Snapshot mode that... Read more
Operate GE’s New Free-Standing KItchen Range...
Think you accidentally left the oven on? Switch it off while on the go. The new free-standing Profile™ Series gas and electric ranges are GE’s second cooking appliances, following their wall oven, to... Read more
Parallels Announces Parallels Desktop 10 for...
The no. 1-selling software for running Windows applications on a Mac becomes an even easier choice for millions of consumers and IT professionals worldwide with the launch of the most powerful... Read more
Apple now offering certified refurbished 2014...
 The Apple Store is now offering Apple Certified Refurbished 2014 MacBook Airs for up to $180 off the cost of new models. An Apple one-year warranty is included with each MacBook, and shipping is... Read more
Best Buy’s College Student Deals: $100 off Ma...
Take an additional $100 off all MacBooks and iMacs, $50 off iPad Airs and iPad minis, at Best Buy Online with their College Students Deals Savings, valid through September 6th. Anyone with a valid .... Read more
MacBook Airs on sale for $100 off MSRP, free...
B&H Photo has three 2014 MacBook Airs on sale for $100 off MSRP. Shipping is free, and B&H charges NY sales tax only. They also include free copies of Parallels Desktop and LoJack for Laptops... Read more
Razer Taipan Mouse For Gamers And Non-Gamers...
If you’re a serious gamer on either Mac or Windows PCs, a serious gaming mouse is a necessity for first-tier performance. However, even if like me you’re not much of a gamer, there’s still a strong... Read more
15-inch 2.2GHz MacBook Pro on sale for $1899,...
Adorama has the new 15″ 2.2GHz Retina MacBook Pro on sale for $1899 including free shipping plus NY & NJ sales tax only. Their price is $100 off MSRP, and it’s the lowest price available for this... Read more

Jobs Board

Project Manager, *Apple* Financial Services...
**Job Summary** Apple Financial Services (AFS) offers consumers, businesses and educational institutions ways to finance Apple purchases. We work with national and Read more
*Apple* Solutions Consultant (ASC)- Retail S...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
Position Opening at *Apple* - Apple (United...
…customers purchase our products, you're the one who helps them get more out of their new Apple technology. Your day in the Apple Store is filled with a range of Read more
*Apple* Retail - Multiple Positions (US) - A...
Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, you're also the Read more
Senior Event Manager, *Apple* Retail Market...
…This senior level position is responsible for leading and imagining the Apple Retail Team's global event strategy. Delivering an overarching brand story; in-store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.