Can abstract base class have V-table?, Will the pointer to virtual destructor be entered into the vi

Discussion in 'C++' started by sojin, Apr 6, 2006.

  1. sojin

    sojin Guest

    Hi all,

    I'm a new to c++... and I've some doubts on "virtual" topics.

    1) Can abstract base class have V-table?

    Here's the way,,

    Class CTemp{

    CTemp(){};
    ~CTemp(){};

    virtual void display() = 0;

    virtual void draw() { cout << " It's ready!!" << endl;}
    }

    Class CDerived : public CTemp{

    CDerived(){};
    ~CDerived(){};

    }

    Can this class CTemp have a v-table?

    2) Will the virtual destructor be entered into the virtual table?

    please give me good directions..

    With rgds
    soj
     
    sojin, Apr 6, 2006
    #1
    1. Advertising

  2. sojin

    Guest

    Sojin

    > Can this [abstract] class CTemp have a v-table?


    Class Ctemp cannot have an object of his type since it is virtual,
    hence if there is no class there is no v-table? Right? Or do not I
    understand your question?

    > 2. Will the virtual destructor be entered into the virtual table?


    But you have not declared the destructor virtual to start with?

    Marc Wentink
     
    , Apr 6, 2006
    #2
    1. Advertising

  3. sojin

    benben Guest

    Re: Can abstract base class have V-table?, Will the pointer to virtualdestructor be entered into the virtual table?

    sojin wrote:
    > Hi all,
    >
    > I'm a new to c++... and I've some doubts on "virtual" topics.
    >
    > 1) Can abstract base class have V-table?
    >
    > Here's the way,,
    >
    > Class CTemp{
    >
    > CTemp(){};
    > ~CTemp(){};
    >
    > virtual void display() = 0;
    >
    > virtual void draw() { cout << " It's ready!!" << endl;}
    > }
    >
    > Class CDerived : public CTemp{
    >
    > CDerived(){};
    > ~CDerived(){};
    >
    > }
    >
    > Can this class CTemp have a v-table?


    Yes

    >
    > 2) Will the virtual destructor be entered into the virtual table?


    Yes

    >
    > please give me good directions..
    >
    > With rgds
    > soj
    >
     
    benben, Apr 6, 2006
    #3
  4. sojin

    al pacino Guest

    sojin wrote:
    > Hi all,
    >
    > I'm a new to c++... and I've some doubts on "virtual" topics.
    >
    > 1) Can abstract base class have V-table?
    >
    > Here's the way,,
    >
    > Class CTemp{
    >
    > CTemp(){};
    > ~CTemp(){};
    >
    > virtual void display() = 0;
    >
    > virtual void draw() { cout << " It's ready!!" << endl;}
    > }
    >
    > Class CDerived : public CTemp{
    >
    > CDerived(){};
    > ~CDerived(){};
    >
    > }
    >
    > Can this class CTemp have a v-table?
    >
    > 2) Will the virtual destructor be entered into the virtual table?
    >
    > please give me good directions..
    >
    > With rgds
    > soj

    yes even though the class is abstract it does have a vtable, in that
    at least on entry for a function is zero.
     
    al pacino, Apr 6, 2006
    #4
  5. sojin

    Samineni Guest

    1. For every class if it contains at least one virtual function (or
    pure virtual function) V-TABLE will be formed. In the case of pure
    virtual fucntions , the corresponding entry of the VTABLE will be NULL.
    When you are trying to instantiate any object of the class, runtime
    will check if the VTABLE will have any NULL entries, if it's so it
    won't alllow you to create any objects of that class.

    2. As per above, virtual destructor also be entered into the virtual
    table as it's a virtual function.


    al pacino wrote:
    > sojin wrote:
    > > Hi all,
    > >
    > > I'm a new to c++... and I've some doubts on "virtual" topics.
    > >
    > > 1) Can abstract base class have V-table?
    > >
    > > Here's the way,,
    > >
    > > Class CTemp{
    > >
    > > CTemp(){};
    > > ~CTemp(){};
    > >
    > > virtual void display() = 0;
    > >
    > > virtual void draw() { cout << " It's ready!!" << endl;}
    > > }
    > >
    > > Class CDerived : public CTemp{
    > >
    > > CDerived(){};
    > > ~CDerived(){};
    > >
    > > }
    > >
    > > Can this class CTemp have a v-table?
    > >
    > > 2) Will the virtual destructor be entered into the virtual table?
    > >
    > > please give me good directions..
    > >
    > > With rgds
    > > soj

    > yes even though the class is abstract it does have a vtable, in that
    > at least on entry for a function is zero.
     
    Samineni, Apr 6, 2006
    #5
  6. sojin

    red floyd Guest

    Re: Can abstract base class have V-table?, Will the pointer to virtualdestructor be entered into the virtual table?

    sojin wrote:
    > Hi all,
    >
    > I'm a new to c++... and I've some doubts on "virtual" topics.
    >
    > 1) Can abstract base class have V-table?


    There is nothing in the Standard that mandates virtual functions be
    provided via vtable. It's an implementation detail. Therefore the
    answer to this question is undefined. Granted, all current
    implementations use a vtable, but it is not required. Assuming a vtable
    implementation, the answer is it will *always* have a vtable.

    > 2) Will the virtual destructor be entered into the virtual table?
    >


    As there is no requirement for a vtable, the answer to this question is
    undefined. However, assuming a vtable implementation, the answer is yes.
     
    red floyd, Apr 6, 2006
    #6
  7. sojin

    sojin Guest

    Thanks for your reply.... my queries ends here....
    now i'm digging to the deep....
    sojin....
     
    sojin, Apr 6, 2006
    #7
  8. sojin

    Kaz Kylheku Guest

    wrote:
    > Sojin
    >
    > > Can this [abstract] class CTemp have a v-table?


    Note that vtables are implementation artifacts. They are not defined by
    the C++ language.

    > Class Ctemp cannot have an object of his type since it is virtual,
    > hence if there is no class there is no v-table?


    There certainly is a class. You might thing that since CTemp cannot be
    instantiated by itself, there is no need for a vtable. However, during
    the construction of a CDerived object, there is a brief moment during
    which the object is considered to be a CTemp, and is not yet a
    CDerived.

    That happens when the CTemp constructor has been entered, but the
    CDerived constructor has not yet been. During this time, if virtual
    functions are called, they have to go to CTemp definitions.

    This cannot be implemented statically, because a constructor can run
    arbitrary code which doesn't know what type the object is:

    void LibraryFunction(CTemp *basePtr)
    {
    basePtr->virtualFunction();
    }

    CTemp::CTemp()
    {
    LibraryFunction(this);
    }

    The virtualFunction() call in LibraryFunction has to
    CTemp::virtualFunction even though the object is really a CDerived, and
    there is a CDerived::virtualFunction.

    LibraryFunction cannot do this by clairvoyance: it has to retrieve some
    type-related information from the object, such as a vtable pointer.

    Even if CTemp is a pure abstract base class (pure virtuals only) so
    that the call to virtualFunction is actually a pure virtual call error,
    there still has to be something in the object to detect that run-time
    error.

    Quite conceivably, if the base class has nothing but pure virtuals,
    perhaps the vtable could be optimized away. The vtable pointer in the
    partially constructed object could just be set to some special value
    (like null). (But then the run-time system would not be able to
    provide a diagnostic which distinguishes between a pure virtual call
    error, and a virtual call on an object that has been stomped-over with
    zero bytes).
     
    Kaz Kylheku, Apr 6, 2006
    #8
  9. sojin

    Howard Guest

    "red floyd" <> wrote in message
    news:w1bZf.52519$...
    > sojin wrote:
    >> Hi all,
    >>
    >> 2) Will the virtual destructor be entered into the virtual table?
    >>

    >
    > As there is no requirement for a vtable, the answer to this question is
    > undefined. However, assuming a vtable implementation, the answer is yes.


    And also assuming that the destructor was actually declared as virtual in
    the first place! :) (It wasn't virtual in the code given.)

    -Howard
     
    Howard, Apr 6, 2006
    #9
  10. sojin

    Kaz Kylheku Guest

    wrote:
    > Sojin
    >
    > > Can this [abstract] class CTemp have a v-table?


    Note that vtables are implementation artifacts. They are not defined by
    the C++ language.

    > Class Ctemp cannot have an object of his type since it is virtual,
    > hence if there is no class there is no v-table?


    There certainly is a class. You might think that since CTemp cannot be
    instantiated by itself, there is no need for a vtable. However, during
    the construction of a CDerived object, there is a brief moment during
    which the object is considered to be a CTemp, and is not yet a
    CDerived.

    That happens when the CTemp constructor has been entered, but the
    CDerived constructor has not yet been. During this time, if virtual
    functions are called, they have to go to CTemp definitions.

    This cannot be implemented statically, because a constructor can run
    arbitrary code which doesn't know what type the object is:

    void LibraryFunction(CTemp *basePtr)
    {
    basePtr->virtualFunction();
    }

    CTemp::CTemp()
    {
    LibraryFunction(this);
    }

    The virtualFunction() call in LibraryFunction has to
    CTemp::virtualFunction even though the object is really a CDerived, and
    there is a CDerived::virtualFunction.

    LibraryFunction cannot do this by clairvoyance: it has to retrieve some
    type-related information from the object, such as a vtable pointer.

    Even if CTemp is a pure abstract base class (pure virtuals only) so
    that the call to virtualFunction is actually a pure virtual call error,
    there still has to be something in the object to detect that run-time
    error.

    Quite conceivably, if the base class has nothing but pure virtuals,
    perhaps the vtable could be optimized away. The vtable pointer in the
    partially constructed object could just be set to some special value
    which summarizes the idea that the object is a pure ABC. Of course,
    the code generated for virtual calls would then have to check for this
    value to detect pure virtual calls.

    (Null would be a poor choice for this value, because, then the run-time
    system would not be able to provide a diagnostic which distinguishes
    between a pure virtual call
    error, and a virtual call on an object that has been stomped-over with
    zero bytes).

    In a sense, that special value could still be considered a vtable,
    albeit a compressed, summarized one.
     
    Kaz Kylheku, Apr 6, 2006
    #10
  11. sojin

    Tomás Guest

    DIY virtual functions

    Okay, well I've a lot of free time today.


    First of all, look at the following code:


    #include <some_header_that_defines_geometrical_shapes>


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

    void PrintObjectInfo( ThreeDimensionalObject& object )
    {
    cout << object.GetClassification() << "\n\nMass: " << object.GetMass()
    <<
    "\n\nSurface Area: " << object.GetSurfaceArea() << "\n\n";
    }


    int main()
    {
    Sphere sphere; sphere.radius = 5;

    Cylinder cylinder; cylinder.height = 2; cylinder.radius = 7;


    PrintObjectInfo( sphere );
    PrintObjectInfo( cylinder );
    }


    The idea in the code above is that the member functions,
    "GetClassification", "GetMass" and "GetSurfaceArea" should be virtual so
    that the function "PrintObjectInfo" can call the appropriate functions.

    I've written a self-sufficient source code file to demonstrate (please keep
    reading as it gets interesting):

    //normal.cpp

    class ThreeDimensionalObject
    {
    public:
    virtual const char* GetClassification() const = 0;
    virtual unsigned long GetMass() const = 0;
    virtual unsigned long GetSurfaceArea() const = 0;
    };

    class Sphere : public ThreeDimensionalObject
    {
    public:
    unsigned long radius;

    virtual const char* GetClassification() const { return "Sphere"; }

    virtual unsigned long GetMass() const
    {
    return (radius * radius * radius) * 3 / 3;
    }

    virtual unsigned long GetSurfaceArea() const
    {
    return radius * radius * 3;
    }
    };

    class Cylinder : public ThreeDimensionalObject
    {
    public:
    unsigned long radius;
    unsigned long height;

    virtual const char* GetClassification() const { return "Cylinder"; }

    virtual unsigned long GetMass() const
    {
    return radius * height;
    }

    virtual unsigned long GetSurfaceArea() const
    {
    return height * 2 / radius;
    }
    };

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

    void PrintObjectInfo( ThreeDimensionalObject& object )
    {
    cout << object.GetClassification() << "\n\nMass: " << object.GetMass()
    <<
    "\n\nSurface Area: " << object.GetSurfaceArea() << "\n\n";
    }


    int main()
    {
    Sphere sphere; sphere.radius = 5;

    Cylinder cylinder; cylinder.height = 2; cylinder.radius = 7;


    PrintObjectInfo( sphere );
    PrintObjectInfo( cylinder );
    }


    So then I thought, how would I achieve this if C++ didn't have virtual
    functions? I'd have to implement the whole V-table concept by myself.

    Step 1: I'm going to have to change the original code slightly:


    #include <some_header_that_defines_geometrical_shapes>

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

    void PrintObjectInfo( ThreeDimensionalObject& object )
    {
    cout << object.vtable->GetClassification(&object) << "\n\nMass: " <<
    object.vtable->GetMass(&object) <<
    "\n\nSurface Area: " << object.vtable->GetSurfaceArea(&object) <<
    "\n\n";
    }


    int main()
    {
    Sphere sphere; sphere.radius = 5;

    Cylinder cylinder; cylinder.height = 2; cylinder.radius = 7;


    PrintObjectInfo( sphere );
    PrintObjectInfo( cylinder );
    }


    Here comes the code I spent the last half hour writing... enjoy!

    //weird.cpp


    struct VTable {};

    // Forward Declarations
    struct ThreeDimensionalObject;
    struct Sphere;
    struct Cylinder;

    struct VTable_ThreeDimensionalObject : public VTable {
    //Pointers to functions

    const char* (*GetClassification)(const ThreeDimensionalObject*);
    unsigned long (*GetMass)(const ThreeDimensionalObject*);
    unsigned long (*GetSurfaceArea)(const ThreeDimensionalObject*);

    VTable_ThreeDimensionalObject(
    const char* (*In_GetClassification)(const ThreeDimensionalObject*),
    unsigned long (*In_GetMass)(const ThreeDimensionalObject*),
    unsigned long (*In_GetSurfaceArea)(const ThreeDimensionalObject*) )
    : GetClassification(In_GetClassification), GetMass(In_GetMass),
    GetSurfaceArea(In_GetSurfaceArea) {}

    };

    struct VTable_Sphere : public VTable_ThreeDimensionalObject {

    //Nothing extra to add in here

    VTable_Sphere(
    const char* (*In_GetClassification)(const ThreeDimensionalObject*),
    unsigned long (*In_GetMass)(const ThreeDimensionalObject*),
    unsigned long (*In_GetSurfaceArea)(const ThreeDimensionalObject*) )
    : VTable_ThreeDimensionalObject
    (In_GetClassification,In_GetMass,In_GetSurfaceArea) {}

    };

    struct VTable_Cylinder : public VTable_ThreeDimensionalObject {

    //Nothing extra to add in here

    VTable_Cylinder(
    const char* (*In_GetClassification)(const ThreeDimensionalObject*),
    unsigned long (*In_GetMass)(const ThreeDimensionalObject*),
    unsigned long (*In_GetSurfaceArea)(const ThreeDimensionalObject*) )
    : VTable_ThreeDimensionalObject
    (In_GetClassification,In_GetMass,In_GetSurfaceArea) {}
    };


    //Forward declarations:
    extern VTable_ThreeDimensionalObject vtable_threedimensionalobject;
    extern VTable_Sphere vtable_sphere;
    extern VTable_Cylinder vtable_cylinder;


    //Now define the classes:

    struct ThreeDimensionalObject {

    VTable_ThreeDimensionalObject* vtable;

    ThreeDimensionalObject() : vtable( &vtable_threedimensionalobject ) {}

    protected:

    ThreeDimensionalObject( VTable_ThreeDimensionalObject* p ) : vtable(p)
    {}
    };

    struct Sphere : public ThreeDimensionalObject {

    Sphere() : ThreeDimensionalObject( &vtable_sphere ) {}

    unsigned long radius;
    };


    struct Cylinder: public ThreeDimensionalObject {

    Cylinder() : ThreeDimensionalObject( &vtable_cylinder ) {}

    unsigned long radius;
    unsigned long height;
    };


    //Define the actual functions

    const char* GetClassification_Sphere( const ThreeDimensionalObject* ) {
    return "Sphere"; }

    unsigned long GetMass_Sphere( const ThreeDimensionalObject* p )
    {
    Sphere const &sphere = *static_cast<const Sphere*>(p);

    return (sphere.radius * sphere.radius * sphere.radius) * 3 / 3;
    }

    unsigned long GetSurfaceArea_Sphere( const ThreeDimensionalObject* p )
    {
    Sphere const &sphere = *static_cast<const Sphere*>(p);

    return sphere.radius * sphere.radius * 3;
    }

    const char* GetClassification_Cylinder( const ThreeDimensionalObject* ) {
    return "Cylinder"; }

    unsigned long GetMass_Cylinder(const ThreeDimensionalObject* p)
    {
    Cylinder const &cylinder = *static_cast<const Cylinder*>(p);

    return cylinder.radius * cylinder.height;
    }

    unsigned long GetSurfaceArea_Cylinder(const ThreeDimensionalObject* p)
    {
    Cylinder const &cylinder = *static_cast<const Cylinder*>(p);

    return cylinder.height * 2 / cylinder.radius;
    }


    //Define the vtable objects:

    VTable_ThreeDimensionalObject vtable_threedimensionalobject(0, 0, 0);

    VTable_Sphere vtable_sphere( GetClassification_Sphere, GetMass_Sphere,
    GetSurfaceArea_Sphere );

    VTable_Cylinder vtable_cylinder( GetClassification_Cylinder,
    GetMass_Cylinder, GetSurfaceArea_Cylinder );


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

    void PrintObjectInfo( ThreeDimensionalObject& object )
    {
    cout << object.vtable->GetClassification(&object) << "\n\nMass: " <<
    object.vtable->GetMass(&object) <<
    "\n\nSurface Area: " << object.vtable->GetSurfaceArea(&object) <<
    "\n\n";
    }


    int main()
    {
    Sphere sphere; sphere.radius = 5;

    Cylinder cylinder; cylinder.height = 2; cylinder.radius = 7;


    PrintObjectInfo( sphere );
    PrintObjectInfo( cylinder );
    }


    Okay so I've alleviated by boredom for about an hour. What next?


    -Tomás
     
    Tomás, Apr 6, 2006
    #11
  12. sojin

    Marcus Kwok Guest

    Re: DIY virtual functions

    "Tom?s" <> wrote:
    > So then I thought, how would I achieve this if C++ didn't have virtual
    > functions? I'd have to implement the whole V-table concept by myself.

    [snip manual implementation of vtables]

    In a similar vein, have you seen Alf P. Steinbach's "Pointers" document?
    (Specifically the section on Polymorphism):
    http://home.no.net/dubjai/win32cpptut/special/pointers/ch_01.pdf

    (You obviously understand what you're doing, but this is for those
    following along at home who might not quite follow what you did.)

    --
    Marcus Kwok
     
    Marcus Kwok, Apr 6, 2006
    #12
  13. sojin

    Guest

    > There certainly is a class. You might think that since CTemp cannot be
    > instantiated by itself, there is no need for a vtable.


    But that was a wrong assumption from my side. Thanks for the lesson!
    It gave me more understanding of the VT concept. :)
     
    , Apr 7, 2006
    #13
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. TN Bella
    Replies:
    1
    Views:
    1,501
    TN Bella
    Jul 1, 2004
  2. Chunhui Han
    Replies:
    2
    Views:
    505
  3. qazmlp
    Replies:
    1
    Views:
    571
    qazmlp
    Apr 10, 2005
  4. frs
    Replies:
    20
    Views:
    755
    Alf P. Steinbach
    Sep 21, 2005
  5. Marcel Müller
    Replies:
    2
    Views:
    121
    Marcel Müller
    Mar 15, 2014
Loading...

Share This Page