Virtual Method Details


Without virtual methods:

class Point1D
{
  public:
    Point1D(double x) : x_(x) {};
  private:
    double x_;
};
class Point2D : public Point1D
{
  public:
    Point2D(double x, double y) : Point1D(x), y_(y) {};
  private:
    double y_;
};

class Point3D : public Point2D
{
  public:
    Point3D(double x, double y, double z) : Point2D(x, y), z_(z) {};
  private:
    double z_;
};
Reading/Writing private data directly: (Professional driver, closed course. Don't try this at home.)

#include <iostream>

int main(void)
{
  Point3D pt3(5, 10, 15);

    // Display private members: 5, 10, 15
  std::cout << *reinterpret_cast<double *>(&pt3) << ", ";
  std::cout << *(reinterpret_cast<double *>(&pt3) + 1) << ", ";
  std::cout << *(reinterpret_cast<double *>(&pt3) + 2) << std::endl;

    // Modify private members
  *reinterpret_cast<double *>(&pt3) = 1;
  *(reinterpret_cast<double *>(&pt3) + 1) = 2;
  *(reinterpret_cast<double *>(&pt3) + 2) = 3;

    // Display private members: 1, 2, 3
  std::cout << *reinterpret_cast<double *>(&pt3) << ", ";
  std::cout << *(reinterpret_cast<double *>(&pt3) + 1) << ", ";
  std::cout << *(reinterpret_cast<double *>(&pt3) + 2) << std::endl;

  return 0;
}

With virtual methods

#include <iostream>

class Point1D
{
  public:
    Point1D(double x) : x_(x) {}
    virtual ~Point1D() {}
    double getX(void) const {return x_;}
    void setX(double x) {x_ = x;}
    virtual void Display(void) 
    { 
      std::cout << x_; 
    }
  private:
    double x_;
};

class Point2D : public Point1D
{
  public:
    Point2D(double x, double y) : Point1D(x), y_(y) {}
    virtual ~Point2D() {}
    double getY(void) const {return y_;}
    void setY(double y) {y_ = y;}
    virtual void Display(void) 
    { 
      Point1D::Display();
      std::cout << ", " << y_;
    }
    virtual void SwapXY(void)
    {
      double x = getX();
      setX(y_);
      y_ = x;
    }
      
  private:
    double y_;
};

class Point3D : public Point2D
{
  public:
    Point3D(double x, double y, double z) : Point2D(x, y), z_(z) {};
    virtual ~Point3D() {}
    double getZ(void) const {return z_;};
    void setZ(double z) {z_ = z;}
    virtual void Display(void) 
    { 
      Point2D::Display();
      std::cout << ", " << z_;
    }
    virtual void SwapXYZ(void)
    {
      double x = getX();
      setX(getY());
      setY(z_);
      z_ = x;
    }
  private:
    double z_;
};
Visually, the classes might look like this:

You can clearly see the extra 4 bytes that are added to each object. Also, the size of the class' corresponding virtual method table is obvious. Things to note:

So, now if we tried to "go through the back door":

Point3D pt3(5, 10, 15);

  // Display private members: 5, 10, 15
std::cout << *reinterpret_cast<double *>(&pt3) << ", ";
std::cout << *(reinterpret_cast<double *>(&pt3) + 1) << ", ";
std::cout << *(reinterpret_cast<double *>(&pt3) + 2) << std::endl;
We'd get this:
-9.25596e+061, 5, 10
We'd have to do this:
  // Display private members: 1, 2, 3
std::cout << *reinterpret_cast<double *>(&pt3) << ", ";
std::cout << *(reinterpret_cast<double *>(&pt3) + 1) << ", ";
std::cout << *(reinterpret_cast<double *>(&pt3) + 2) << std::endl;
The example above "seemed" to work with both Microsoft's 7.1 compiler and GNU's g++ 3.3 compiler. Borland's 5.6 compiler printed the y and z values correctly, but printed garbage for x:
5.31147e-315, 10, 15