Thursday 30 July 2009

Virtual Base class Inheritance


Came across this interesting case of multiple base class inheritance which can result in compilation errors.

Figure above demonstrates the ambiguity that can occur in diamond inheritance. The program defines class Base, which contains pure virtual function print. Classes DerivedOne and DerivedTwo each publicly inherit from class Base and override the print function. Class DerivedOne and class DerivedTwo each contain what the C++ standard refers to as a base-class subobject—i.e., the members of class Base in this example.

Class Multiple inherits from both classes DerivedOne and DerivedTwo. In class Multiple, function print is overridden to call DerivedTwo’s print.

Function main declares objects of classes Multiple, DerivedOne and DerivedTwo. main also declares an array of Base * pointers. Each array element is initialized with the address of an object. An error occurs when the address of both—an object of class Multiple—is assigned to array[ 0 ]. The object both actually contains two subobjects of type Base, so the compiler does not know which subobject the pointer array[ 0 ] should point to, and it generates a compilation error indicating an ambiguous conversion.

The problem of duplicate subobjects is resolved with virtual inheritance. When a base class is inherited as virtual, only one subobject will appear in the derived class—a process called virtual base-class inheritance.



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Example showing virtual base class inheritance
//http://www.deitel.com/articles/cplusplus_tutorials/20060225/virtualBaseClass/index.html

#include <iostream>
using std::cout;
using
std::endl;

// class Base definition
class Base
{

public
:
virtual
void print() const = 0; // pure virtual
}; // end class Base

// class DerivedOne definition
//class DerivedOne : public Base - REF1
class DerivedOne : virtual public Base
{

public
:
// override print function
void print() const
{

cout << "DerivedOne\n";
}
// end function print
}; // end class DerivedOne

// class DerivedTwo definition
//class DerivedTwo : public Base - REF2
class DerivedTwo : virtual public Base
{

public
:
// override print function
void print() const
{

cout << "DerivedTwo\n";
}
// end function print
}; // end class DerivedTwo

// class Multiple definition
class Multiple : public DerivedOne, DerivedTwo
{

public
:
// qualify which version of function print
void print() const
{

DerivedTwo::print();
}
// end function print
}; // end class Multiple

int
main()
{

Multiple both; // instantiate Multiple object
DerivedOne one; // instantiate DerivedOne object
DerivedTwo two; // instantiate DerivedTwo object
Base *array[ 3 ]; // create array of base-class pointers

array[ 0 ] = &both; // ERROR - ambiguous if REF1 and REF2 used
array[ 1 ] = &one;
array[ 2 ] = &two;

// polymorphically invoke print
for ( int i = 0; i < 3; i++ )
array[ i ] -> print();

return
0;
}
// end main

The output is as follows:


Monday 27 July 2009

Example of C++ STL 'pair' container

The pair container is a rather basic container. It can be used to store two elements, called first and second, and that's about it. To define a variable as a pair container, the header file must be included. 'pair' can do basic features like assignment and comparisons and has no further special features. It is, however, a basic ingredient of the abstract containers map, multimap and hash_map.

Lets look at the example now:



//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//A simple example of C++ STL container 'pair'
#include<iostream>
#include<string>
#include<utility>

using namespace
std;

int
main()
{

pair<string, string> name("Zahid","Ghadialy"); //firstname, lastname
string custName = name.first+" "+name.second;
pair<string, int> customerNum(custName, 23456); //firstname, cust. no.
pair<int, int> customerAge(customerNum.second, 30); //cust. no., age

cout<<"Customer Full Name = "<<custName<<endl;
cout<<"Customer Number of "<<customerNum.first<<" is "<<customerNum.second<<endl;
cout<<"Age of Customer Number = "<<customerAge.first<<" is "<<customerAge.second<<endl;

//If we now want to increment say, age by 1
customerAge.second++;
cout<<"New age of Customer Number = "<<customerAge.first<<" is "<<customerAge.second<<endl;

return
0;
}

The output is as follows:


Sunday 26 July 2009

Initialising References in a class

Unassigned references cannot exist for a class. There is no C++ concept of an "unassigned reference" and the behavior of any program that has one is undefined. If a class contains a reference then it must be initialised through an initialiser list. You can't declare a reference variable in the class and then assign it later on. Non-reference variables and pointers can be left uninitialised but references must have a value upon entry. The only way to do this is through an initialiser.


//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Example showing initializing of refrences in a class
#include<iostream>

using namespace
std;

class
A
{

public
:
A(string &name);
void
print()
{

cout<<"a = "<<a<<" and s = "<<s.c_str()<<endl;
}

void
set_a(int x) {a = x;}
private
:
A(); //Shouldnt really be called because we need to have a reference
int a;
string &s;
};


A::A(string &name): s(name)
{

//s = name; - error. Should be in initialiser
a = 0;
}


int
main()
{

string z = "zahid";
A a(z);
a.print();
z = "christian";
a.print();
a.set_a(30);
a.print();
return
0;
}

The output is as follows:

Monday 20 July 2009

Simple example of BitSets in C++

From "The C++ Standard Library" By Nicolai M Josuttis: A bitset is a bitfield with an arbitrary but fixed number of bits. You can consider it a container for bits or Boolean values. Note that the C++ standard library also provides a special container with a variable size for Boolean values: vector.

Lets write a simple program using rainbow colours.


//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Simple example of BitSets
#include<iostream>
#include<bitset>

using namespace
std;

int
main()
{

enum
Colour {red, orange, yellow, green, blue, indigo, violet, numOfColours};

bitset<numOfColours> usedColours;

usedColours.set(red);
usedColours.set(blue);

//Lets see the output
cout << "bitfield of used colours: " << usedColours << endl;
cout << "number of used colors: " << usedColours.count() << endl;
cout << "bitfield of unused colors: " << ~usedColours << endl;

//If any colour is used
if (usedColours.any())
{

// loop over all colors
for (int c = 0; c < numOfColours; ++c)
if
(usedColours[(Colour)c])
cout << Colour(c)<< " used "<<endl; //No way to print enum names directly
}

return
0;
}

The output is as follows:


Reference:


Monday 13 July 2009

Example of C++ class invariant

According to Bjarne Stroustrup in 'The C++ Programming Language':

The values of the members and the objects referred to by members are collectively called the state of the object (or simply, its value). A major concern of a class design is to get an object into a well defined state (initialization/construction), to maintain a well defined state as operations are performed, and finally to destroy the object gracefully. The property that makes the state of an object well-defined is called its invariant.

Thus, the purpose of initialization is to put an object into a state for which the invariant holds. Typically, this is done by a constructor. Each operation on a class can assume it will find the invariant true on entry and must leave the invariant true on exit. The destructor finally invalidates the invariant by destroying the object.

Another way of writing the same thing:

A class invariant is a condition that defines all valid states for an object. It is a logical condition to ensure the correct working of a class. Class invariants must hold when an object is created, and they must be preserved under all operations of the class. In particular all class invariants are both preconditions and post-conditions for all operations or member functions of the class.

The conditions that have to be met for a condition to be an invariant of the class are:
=> The condition should hold at the end of every constructor.
=> The condition should hold at the end of every mutator (non-const) operation.

Lets look at an example. Suppose we are designing a system where the user input some pressure to be applied. The pressure can be between 30 and 100 units. A user should not be allowed to put pressure outside these bounds:


//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Example of class invariant
#include<iostream>

using namespace
std;

const
int PressureOverflow = 1;
const
int PressureUnderflow = 2;

const
int MIN_PRESSURE = 30;
const
int MAX_PRESSURE = 100;

class
Pressure
{

public
:
Pressure();
void
setPressure(int p);
void
displayPressure(void) const;
private
:
int
pressureMonitor; //invariant
};

Pressure::Pressure()
{

pressureMonitor = 30;
}


void
Pressure::setPressure(int p)
{

try

{

if
(p < MIN_PRESSURE)
throw
PressureUnderflow;
if
(p > MAX_PRESSURE)
throw
PressureOverflow;
pressureMonitor = p;
}

catch
(int pError)
{

switch
(pError)
{

case
PressureUnderflow:
pressureMonitor = MIN_PRESSURE;
cout<<"ERROR: Pressure should be between "<<MIN_PRESSURE<<" and "<<
MAX_PRESSURE<<" - Value set to "<<pressureMonitor<<endl;
break
;
case
PressureOverflow:
pressureMonitor = MAX_PRESSURE;
cout<<"ERROR: Pressure should be between "<<MIN_PRESSURE<<" and "<<
MAX_PRESSURE<<" - Value set to "<<pressureMonitor<<endl;
break
;
default
:
break
;
}
}
}


void
Pressure::displayPressure(void) const
{

cout<<"Current Pressure set to: "<<pressureMonitor<<endl;
}


int
main()
{

Pressure p;
int
x=0;
while
(1)
{

p.displayPressure();
cout<<"Enter new Pressure: ";
cin>>x;
p.setPressure(x);
}


return
0;
}


The output is as follows:

Monday 6 July 2009

Example of 'pointer to const' and 'const pointer'

Continuing with the const correctness theme:


//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Example of pointer to const and const pointer
#include<iostream>

using namespace
std;

int
main()
{

//Lets look at const with pointers
int a = 34;
int
b = 2009;

int
*const x = &a; //COMPULSARY: const object must be initialized
cout<<"*x(1) = "<<*x<<endl;

*
x = 33;
cout<<"*x(2) = "<<*x<<endl;

//x = &b; - NOT POSSIBLE because x is const

const
int *y;
y = &b;
cout<<"*y(1) = "<<*y<<endl;

//*y = 2004; - NOT POSSIBLE
y = x; // POSSIBLE
cout<<"*y(2) = "<<*y<<endl;

int
c = 23456;
int
const *z=&c;
cout<<"*z(1) = "<<*z<<endl;
//*z = 77777; - NOT POSSIBLE, same as *y case
z = x; //POSSIBLE
cout<<"*z(2) = "<<*z<<endl;

//Now lets look const variables
const int i = 1111;
int
const j = 4444;
//i = 66; - NOT POSSIBLE
//j = 77; - NOT POSSIBLE, exactly same as i
//But we can manipulate i or j using pointers and const_cast
int *k = const_cast<int *>(&i);
cout<<"*k(1) = "<<*k<<endl;
*
k = 5678;
cout<<"*k(2) = "<<*k<<endl;
cout<<"i = "<<i<<endl; //Should be 5678 but output maybe 1111
//Change i to const volatile int i = 1111; to get the desired result

return
0;
}


The output is as follows:

It may be sometimes confusing to remember is the const is associated with the pointer or the variable. A simpler way to remember is that const is applied to whatever it is near. Another thing is that You have to read pointer declarations right-to-left. So:

  • const Fred* p means "p points to a Fred that is const" — that is, the Fred object can't be changed via p.
  • Fred* const p means "p is a const pointer to a Fred" — that is, you can change the Fred object via p, but you can't change the pointer p itself.
  • const Fred* const p means "p is a const pointer to a const Fred" — that is, you can't change the pointer p itself, nor can you change the Fred object via p.

Saturday 4 July 2009

A simple example of pointer-to-const

What is "const correctness"?

"const correctness" means using the keyword const to prevent const objects from getting mutated.

In this example we show passing by pointer-to-const. In case of pass by pointer-to-const, any attempts to change to the caller's variable within the function would be flagged by the compiler as an error at compile-time. This check is done entirely at compile-time: there is no run-time space or speed cost for the const. Also passing by pointer-to-const is more efficient as it avoids temporary objects.

So here is the example:


//Program tested on Microsoft Visual Studio 2008 - Zahid Ghadialy
//Simple program to show const pointers
#include<iostream>

using namespace
std;

class
A
{

public
:
int
*var;
};


void
someFunc(const A* a)
{

//int b=200;
//a = &b; - Not Possible to convert int* to const int*
// We can use a const_cast but thats not the purpose here
*(a->var) = 200; //Possible to change value of const pointer
}

void
anotherFunc(const A* a)
{

if
(a)
{

if
(a->var)
delete
a->var;
delete
a;
}
}


int
main()
{

A *a = new A;
a->var = new int(1024);
cout<<"1: a->var = "<<*(a->var)<<endl;
someFunc(a);
cout<<"2: a->var = "<<*(a->var)<<endl;
anotherFunc(a);
//cout<<"3: a->var = "<<*(a->var)<<endl; - Not Valid
return 0;
}
 


The output is as follows:

Friday 3 July 2009

C++ Syntax Puzzle

This is an interesting puzzle and possibly an interiew question:

Without attempting to compile it, is the following code compilable? Is t in scope in the if body or the else?


#include <iostream>

using namespace
std;

int
returnanint() {
return
1;
}


using namespace
std;
int
main(int argc, char * argv[])
{

if
(int t=returnanint()) {
cout << "t > 0 = " << t << endl;
}

else
{
cout << "t==0 " << endl;
t++;
}

return
0;
}


Answer below
.
.
.
.
.
.
.
.
.
.
.
.
.
The answer is, yes it compiles. It's an interesting and certainly not intuitive gray area of C++. The int is declared outside of the braces following the if so is in scope for both those braces and those for the else branch.