Sunday, September 08, 2013

C++ declarations



consider C++ declaration

const int *kings[];  
what is it ? is it an array of pointers to ints or pointer to array of ints ?

The Rule is simple:
  • There are two types of operators in the declarations prefix and postfix. 
  • postfix operators bind tighter than prefix ones.
  • thus const int *kings[]  is array of pointers. where as to declare pointer to array you have to use brackets.
  • const int (* kings)[]; // now we have increased precedence of * by brackets and hence it is pointer to array of ints
const int *kings[]; //array of pointers of ints .
const int (*kings)[]; //pointer to array of ints

similarly

const int (*kings)(); //pointer to a function taking no params and returning const int.

be aware where the brackets go 

const (int *) kings[] /// is WRONG.

Tuesday, July 30, 2013

Loops

Beware of unsigned variables when writing the counting down loops.

unsigned types wrap around to give a very large positive numbers and loop never ends.

e.g.

for(size_t var (8); var >=0; --var) { //this is an infinite loop }

where as

for(int var(8); var>=0; --var) { // is a finite loop }

here var is int ( signed type) hence it will eventually become negative hence loop will terminate.

worth paying attentions to such pitfalls.

Saturday, June 22, 2013

Bash bits and pieces


  • Create a file named -i in the directory like $touch a; mv a -i;
  • Now if you to accidentally rm * , file -i will be treated as argument to rm and will run rm command in interactive mode preventing accidental deletion of files.
  • Even if you delete all the files following the interactive command file -i will not be deleted.
  • Enjoy!

Saturday, May 11, 2013

Inheritance for encapsulation. Some sort of design pattern.

Inheritance for encapsulation. Some sort of design pattern.

Today we are going to see how inheritance can be used to hide implementation details.
We have 
PersonInterface - Abstract class ( PersonInterface.{h,cpp} )
RealPerson - Derived from PersonInterface and implements PersonInterface.
(RealPerson.{h,cpp}
main.cpp - the main function.

PersonInterface.h

//
//  PersonInterface.h
//  InterfaceDemo
//
//  Created by Mandar Vaidya on 10/05/2013.
//  Copyright (c) 2013 Mandar Vaidya. All rights reserved.
//

#ifndef __InterfaceDemo__PersonInterface__
#define __InterfaceDemo__PersonInterface__
#include<string>

class PersonInterface {
public:
    virtual ~PersonInterface(){};
    virtual std::string name() const =0;
    virtual std::string address() const=0;
    //NOTE: I am returning a pointer.. it is bad idea instead I should have returned a shared_ptr.
    //      This is just to elaborate the concept.
    //This function is a public function implementation inside the abstract class
    //This returns the object of derived class refer. Effective C++ 3rd Ed. Item 31
    //      1. This is a factory function.
    //      2. This is public static function in base class or interface class that returns
    //         derived class object.
    static PersonInterface* create(const std::string& name, const std::string& address);
};
#endif /* defined(__InterfaceDemo__PersonInterface__) */

PersonInterface.cpp

//
//  PersonInterface.cpp
//  InterfaceDemo
//
//  Created by Mandar Vaidya on 10/05/2013.
//  Copyright (c) 2013 Mandar Vaidya. All rights reserved.
//

#include "PersonInterface.h"
#include "RealPerson.h"
//NOTE: I am returning a pointer.. it is bad idea instead I should have returned a shared_ptr.
//      This is just to elaborate the concept.
//This function is a public function implementation inside the abstract class
//This returns the object of derived class refer. Effective C++ 3rd Ed. Item 31
//      1. This is a factory function.
//      2. This is public static function in base class or interface class that returns
//         derived class object.
PersonInterface* PersonInterface::create(const std::string& name, const std::string& address)
{
    return new RealPerson(name,address);
}P

RealPerson.h

//
//  RealPerson.h
//  InterfaceDemo
//
//  Created by Mandar Vaidya on 10/05/2013.
//  Copyright (c) 2013 Mandar Vaidya. All rights reserved.
//

#ifndef __InterfaceDemo__RealPerson__
#define __InterfaceDemo__RealPerson__

#include "PersonInterface.h"

class RealPerson :public PersonInterface
{
public:
    RealPerson(const std::string& name, const std::string& address);
    
    virtual ~RealPerson();
    virtual std::string name() const;
    virtual std::string address() const;
    
private:
    std::string theName;
    std::string theAddress;
    
};
#endif /* defined(__InterfaceDemo__RealPerson__) */

RealPerson.cpp

//
//  RealPerson.cpp
//  InterfaceDemo
//
//  Created by Mandar Vaidya on 10/05/2013.
//  Copyright (c) 2013 Mandar Vaidya. All rights reserved.
//

#include "RealPerson.h"

RealPerson::RealPerson(const std::string& name, const std::string& address)
: theName(name), theAddress(address)
{
}

RealPerson::~RealPerson(){}
std::string RealPerson::name() const
{
    return theName;
}
std::string RealPerson::address() const
{
    return theAddress;
}

Main.cpp

//
//  main.cpp
//  InterfaceDemo
//
//  Created by Mandar Vaidya on 10/05/2013.
//  Copyright (c) 2013 Mandar Vaidya. All rights reserved.
//

#include <iostream>
#include "PersonInterface.h"

int main(int argc, const char * argv[])
{
    PersonInterface* ptr = PersonInterface::create("MANDAR","31 Salders Court");
    
    std::cout << "Name: " << ptr->name() << " Address: " << ptr->address();
    
    delete ptr;
    
    return 0;
}

Analysis:

  • PersonInterface is an abstract class and provides the interface for personal details such as name and address etc.
  • There are only interface methods declared as pure virtual in the base class. Note that member variables are not declared/ defined.
  • Base class also has a static function that takes in parameters, which then creates and returns derived class object on heap.
  • Note: Actually create function ( also called as factory method ) should return the shared pointer to enable RAII and prevent accidental memory leak in case object is not deleted. but this is a quick example hence I have got away with the pointer.
  • RealPerson class is derived from PersonInterface and it defines its own private member variables. It also implements the interface provided by PersonInterface.
  • It also provides public constructor so that base class's static function can create its object.
  • If you now look at main.cpp It only depends on PersonInterface shown by including PersonInterface.h only. RealPerson is hidden from the main function and it's implementation can change any time as long as public interfaces remain same.
  • As main function doesn't depend on the RealPerson, even if it changes, recompilation of main.cpp is not required only new object file is linked with main.obj. This way dependency is reduced.
  • Also note that runtime polymorphism is in play as PersonInterface pointer is used to refer to RealPerson object. 
  • Also strongly note that both the destructors (base and derived) are marked as virtual so that runtime polymorphism works. 

Thursday, April 25, 2013

Namespaces and Linkage demystified....

What is translation unit ?

A translation unit is the source code that gives rise to single object file. It is basically a single source file, plus all of its #include files. 

More elaboration on this. C++ code is compiled in two steps. In the first pass preprocessing is done. Preprocessing includes macro processing and bringing in the entire   file(s) included by #include directive.  The result of the first pass is called as translation unit. So, what programmer presents to compiler is  a 'source file' e.g. .cpp and what compiler sees is a translation unit. Translation unit plays very important role visibility and linkage.

Modularity - A design decision.

A program is composed of modules. Each module can be composed of following things. Modularities are of two types. Physical and Logical.
  • Namespaces
  • Classes
  • Templates
  • Design Patterns ( composed of above three )
  • Libraries ( STL, boost etc)
  • Processes, Threads ( OS, concepts), interprocess communication.
  • Shared memory, Pipes, mutex etc.
  • Files ( physical )
The files is the only physical way of achieving modularity, but for C++ , files are just means of organising the source code, and unfortunately we tend to think of modularity in terms of files, instead we should think modularity in terms of the other logical things.
Main aim of the the design decisions is to increase the modularity and decrease the dependency between the modules, that way design becomes clear, dependency reduces and program also compiles faster. Logical structure of program may not be same as that of physical structure across the files. e.g. namespaces are open and can span across multiple source files. But Logical structure should guide the physical structure of the program. Bottom line is we should think in terms of modules, translation units and logical modules only.

Modular compilation.

Compiler compiles each module rather translation unit separately in isolation from the rest of the program and linker then links all the modules together. It is programmers job to ensure that all the declaration required for each module to compile successfully should be consistent across the program as if all the modules are part of single source file. If this requirement is not satisfied, linker produces errors.


Linkage.

Now is the time to understand linkage....by examples.

//file1.cpp
int m = 1;         //definition
int y;               //definition ...means int y = 0;
int f() { //do something}   //function definition
void another(){//another function}
double duplicate; //OK

//file2.cpp
extern int m;    //declaration.
int y =2;
extern int z= 9; //definition; extern is ignored. any declaration with initialiser is definition.
int f();  //function declaration 
void g() { m = f(); } //function call.
another(); //function call , error: another is not declared here.
double duplicate;  //OK

Let us analyse this step by step.

  • m is defined in file.cpp and declared using extern keyword in file2.cpp, this is ok, extern indicates it is a declaration and the variable is defined in some other translation unit.
  • extern int z = 9; This is definition and NOT declaration. Remember any declaration with initialiser is definition. Here extern is ignored. 
  • The only exception to rule above is: variables defined without initialiser in either 
    • global scope OR
    • namespace scope . e.g. int y; in file1.cpp is definition and NOT declaration. i.e. global or namespace scoped variables are initialised by default.
    • This does not apply to local ( automatic) and objects created on free store.
  • Now there is error with variable y. It is defined twice. This is not allowed in C++. C++ follows one definition rule or ODR. More on this follows.
  • function call another() in file2.cpp is an error too. another() is not declared in file2.cpp
  • Finally definition double duplicate; is OK. This conforms to ODR more on this follows.

External Linkage:

Name that can be used in the translation units different from the one in which it was defined is said to have external linkage. All the names in the example above have external linkage. 

Internal Linkage:

A name that can be referred only in the translation unit in which it is defined is said to have internal linkage.