Thursday, February 26, 2009

Member access

Member access determines if a class member is accessible in an expression or declaration. Suppose x is a member of class A. Class member x can be declared to have one of the following levels of accessibility:

  • public: x can be used anywhere without the access restrictions defined by private or protected.
  • private: x can be used only by the members and friends of class A.
  • protected: x can be used only by the members and friends of class A, and the members and friends of classes derived from class A.

Members of classes declared with the keyword class are private by default. Members of classes declared with the keyword struct or union are public by default.

To control the access of a class member, you use one of the access specifiers public, private, or protected as a label in a class member list. The following example demonstrates these access specifiers:

struct A {
  friend class C; private:   int a; public:   int b; protected:   int c;
};
struct B : A {
  void f() {     // a = 1;     b = 2;     c = 3;   }
};
struct C {
  void f(A x) {     x.a = 4;     x.b = 5;     x.c = 6;
  }
};
int main() {
  A y; //  y.a = 7;   y.b = 8; //  y.c = 9;    B z; //  z.a = 10;   z.b = 11; //  z.c = 12;
}

The following table lists the access of data members A::a A::b, and A::c in various scopes of the above example.

Scope A::a A::b A::c
function B::f() No access. Member A::a is private. Access. Member A::b is public. Access. Class B inherits from A.
function C::f() Access. Class C is a friend of A. Access. Member A::b is public. Access. Class C is a friend of A.
object y in
main()
No access. Member y.a is private. Access. Member y.a is public. No access. Member y.c is protected.
object z in main() No access. Member z.a is private. Access. Member z.a is public. No access. Member z.c is protected.

An access specifier specifies the accessibility of members that follow it until the next access specifier or until the end of the class definition. You can use any number of access specifiers in any order. If you later define a class member within its class definition, its access specification must be the same as its declaration. The following example demonstrates this:

class A {
    class B;   public:     class B { };
};

The compiler will not allow the definition of class B because this class has already been declared as private.

A class member has the same access control regardless whether it has been defined within its class or outside its class.

Access control applies to names. In particular, if you add access control to a typedef name, it affects only the typedef name. The following example demonstrates this:

class A {
    class B { };   public:     typedef B C;
};
int main() {
  A::C x; //  A::B y;
}

The compiler will allow the declaration A::C x because the typedef name A::C is public. The compiler would not allow the declaration A::B y because A::B is private.

Note that accessibility and visibility are independent. Visibility is based on the scoping rules of C++. A class member can be visible and inaccessible at the same time.

Abstract class

An abstract class is a class that is designed to be specifically used as a base class. An abstract class contains at least one pure virtual function. You declare a pure virtual function by using a pure specifier (= 0) in the declaration of a virtual member function in the class declaration.
The following is an example of an abstract class:
class AB {
public:
virtual void f() = 0;
};


Wednesday, February 25, 2009

Virtual Function

A function call with the correct function definition at compile time. This is called static binding. You can specify that the compiler match a function call with the correct function definition at run time; this is called dynamic binding. You declare a function with the keyword virtual if you want the compiler to use dynamic binding for that specific function.

A virtual function is a member function you may redefine for other derived classes, and can ensure that the compiler will call the redefined virtual function for an object of the corresponding derived class, even if you call that function with a pointer or reference to a base class of the object.

A class that declares or inherits a virtual function is called a polymorphic class.

The following example demonstrates this:

#include  using namespace std;
struct A {    virtual void f() { cout << "Class A" <<>
struct B: A {    void f(int) { cout << "Class B" <<>
struct C: B {    void f() { cout << "Class C" <<>
int main() {
   B b; C c;
   A* pa1 = &b;
   A* pa2 = &c;
   pa1->f();
   pa2->f();
}

The following is the output of the above example:

Class A 
Class C

The function B::f is not virtual. It hides A::f. Thus the compiler will not allow the function call b.f(). The function C::f is virtual; it overrides A::f even though A::f is not visible in C.

If you declare a base class destructor as virtual, a derived class destructor will override that base class destructor, even though destructors are not inherited.

Inheritance

Inheritance is a mechanism of reusing and extending existing classes without modifying them, thus producing hierarchical relationships between them.

Multiple inheritance allows you to create a derived class that inherits properties from more than one base class. Because a derived class inherits members from all its base classes, ambiguities can result. For example, if two base classes have a member with the same name, the derived class cannot implicitly differentiate between the two members. Note that, when you are using multiple inheritance, the access to names of base classes may be ambiguous.

A direct base class is a base class that appears directly as a base specifier in the declaration of its derived class.

An indirect base class is a base class that does not appear directly in the declaration of the derived class but is available to the derived class through one of its base classes. For a given class, all base classes that are not direct base classes are indirect base classes.

Constructor & Destructor

Constructor :- 
Constructor creates an object and initializes it. It also creates V-Table for virtual functions. It is different from other methods in a class.
Constructors are used to create, and can initialize, objects of their class type. 
You cannot declare a constructor as virtual or static, nor can you declare a constructor as const, volatile, or const volatile. 
You do not specify a return type for a constructor. A return statement in the body of a constructor cannot have a return value.

Virtual Constructor :-
It is not possible to have Virtual Constructor.The constructor can’t be virtual as the constructor is a code which is responsible for creating an instance of a class and it can’t be delegated to any other object by virtual keyword means.

Destructor :- 
Destructors are usually used to deallocate memory and do other cleanup for a class object and its class members when the object is destroyed. A destructor is called for a class object when that object passes out of scope or is explicitly deleted.

Virtual Destructor :- 
A Virtual destructor can be virtual as it is possible as at runtime depending on the type of object caller is calling to, proper destructor will be called.

pseudo-destructor :-
A pseudo-destructor is a destructor of a nonclass type.
The following example calls the pseudo destructor for an integer type:
typedef int I;
int main() {
I x = 10;
x.I::~I();
x = 20;
}

The call to the pseudo destructor, x.I::~I(), has no effect at all. Object x has not been destroyed; the assignment x = 20 is still valid. Because pseudo destructors require the syntax for explicitly calling a destructor for a nonclass type to be valid, you can write code without having to know whether or not a destructor exists for a given type.