views:

1072

answers:

8

Update: This issue is caused by bad memory usage, see solution at the bottom.

Here's some semi-pseudo code:

class ClassA
{
public:
    virtual void VirtualFunction();
    void SomeFunction();
}

class ClassB : public ClassA
{
public:
    void VirtualFunction();
}

void ClassA::VirtualFunction()
{
    // Intentionally empty (code smell?).
}

void ClassA::SomeFunction()
{
    VirtualFunction();
}

void ClassB::VirtualFunction()
{
    // I'd like this to be called from ClassA::SomeFunction()
    std::cout << "Hello world!" << endl;
}

The C# equivalent is as follows: Removed C# example, as it's not relevant to the actual problem.

Why isn't the ClassB::VirtualFunction function being called when called from ClassA::SomeFunction? Instead ClassA::VirtualFunction is being called...

When I force implementation of the virtual function ClassA::VirtualFunction, like so:

class ClassA
{
public:
    virtual void VirtualFunction() = 0;
    void SomeFunction();
}

class ClassB : public ClassA
{
public:
    void VirtualFunction();
}

void ClassA::SomeFunction()
{
    VirtualFunction();
}

void ClassB::VirtualFunction()
{
    // I'd like this to be called from ClassA::SomeFunction()
    std::cout << "Hello world!" << endl;
}

The following error occurs at runtime, despite the derrived function deffinately being declared and defined.

pure virtual method called
terminate called without an active exception

Note: It seems like the error can be caused even by bad memory usage. See self-answer for details.

Update 1 - 4:

Comments removed (not releavnt).

Solution:

Posted as an answer.

+1  A: 

When A calls VirtualFunction() it will automatically call the version on B. That is the point of virtual functions.

I am not as familiar with the C++ syntax tho. Do you have to declare the function to be virtual at the point of the body as well as in the header?

Alsop, in class B you probably need to mark it as override

in C# its easy. I just don't know the c++ syntax.

public class ClassA
{
    public **virtual** void VirtualFunction(){}

    public void FooBar()
    {
        // Will call ClassB.VirtualFunction()
        VirtualFunction();
    } 

}

public class ClassB
{
    public **overide** void VirtualFunction()
    {
        // hello world
    }
}
Jason Coyne
On the syntax issue: you only write 'virtual' in the declaration of the class, not in the implementation. In C++ there is no such thing as 'override'.
David Rodríguez - dribeas
+5  A: 
class Base {
public:
   virtual void f() { std::cout << "Base" << std::endl; }
   void call() { f(); }
};
class Derived : public Base {
public:
   virtual void f() { std::cout << "Derived" << std::endl; }
};
int main()
{
   Derived d;
   Base& b = d;
   b.call(); // prints Derived
}

If in the Base class you do not want to implement the function you must declare so:

class Base {
public:
   virtual void f() = 0; // pure virtual method
   void call() { f(); }
};

And the compiler won't allow you to instantiate the class:

int main() {
   //Base b; // error b has a pure virtual method
   Derived d; // derive provides the implementation: ok
   Base & b=d; // ok, the object is Derived, the reference is Base
   b.call();
}

As a side note, be careful not to call virtual functions from constructors or destructors as you might get unexpected results.

David Rodríguez - dribeas
Thanks, is what I'm missing simply declaring virtual on the ClassB implementation?
nbolton
You do not need to declare the method virtual in ClassB. Once it has been declared as virtual in the Base class, it will be virtual whether you declare it or not. It is a good style practice to reinforce the fact for readers to write 'virtual' at all levels, but for the compiler it is the same.
David Rodríguez - dribeas
@dribeas: This seems to have worked when called outside the class; ImageMatrix::GetPixelsAsInt32 is called successfully. However, ImageMatrix::GetPixelAt is not being called for some reason... Any ideas? Thanks!
nbolton
Are you calling the virtual function from within the constructor??
David Rodríguez - dribeas
@dribeas: Deleted my poor answer in favor of yours :)
nbolton
A: 

You aren't defining the function in ClassB correctly, it should be:

public class ClassB
{
    public void override AbstractFunction()
    {
        // hello world
    }
}

Then, any call from the base class to virtual/abstract methods will call the implementation on the derived instance.

casperOne
Corrected. Thanks. It's been a while.
nbolton
@Martin York: Look at the original revision, it had C# examples and was specifically tagged "C#".
casperOne
A: 

If you want to force the derived classes to implement the VirtualFunction:

class ClassA
{
public:
    virtual void VirtualFunction()=0;
    void SomeFunction();
}

This is C++. Default the derived function will be called.

If you want to call the base-class function do:

void ClassA::SomeFunction()
{
    // ... various lines of code ...

     ClassA::VirtualFunction();
}
To1ne
The =0 works in C++, in C# it's abstract void Fun();
Henk Holterman
Wrong: Just Calling VirtualFunction() will call the implementation defined in the current class. Using XX::VirtualFunction() allows you to access definitions in parent class. Use pointer or reference to activate virtual dispatch.
Martin York
A: 

There's nothing wrong with your code but your sample is incomplete. You do not state where you are calling SomeFunction from.

As has already been pointed out by dribeas you must be careful calling virtual functions from your constructor as the virtual tables are only built up as each class in the hierarchy completes construction.

Edit: The following paragraph of my reply was incorrect. Apologies. It is fine to call SomeFunction from the constructor of ClassB as the vtable is in place (at least) by the end of the initialiser list i.e. once you are in the body of the constructor. It is not fine to call it from ClassA's constructor of course.

Original paragraph:

I suspect you must be calling SomeFunction from the constructor of ClassB at which point only the vtable up to type ClassA will be complete i.e. to the virtual dispatch mechanism your class is still of type ClassA. It only becomes an object of type ClassB when the constructor completes.

Troubadour
There is something wrong with the code. It does not use the virtual dispatch mechanism.
Martin York
+3  A: 

If you're getting that 'pure virtual method called terminate called without an active exception' error message, that means you're calling the virtual function from the constructor or destructor of classA (the base class), which you should not do.

Chris Dodd
+2  A: 

on the pure virtual method called error:

You should create a different question as it is in fact different than the other. The answer to this question is on the very last paragraph of my previous answer to your initial question:

Do not call virtual functions from constructors or destructors

class Base
{
public:
   Base() { f(); }
   virtual void f() = 0;
};
class Derived : public Base
{
public:
   virtual void f() {}
};
int main()
{
   Derived d; // crashes with pure virtual method called
}

The problem in the code above is that the compiler will allow you to instantiate an object of type Derived (as it is not abstract: all virtual methods are implemented). The construction of a class starts with the construction of all the bases, in this case Base. The compiler will generate the virtual method table for type Base, where the entry for f() is 0 (not implemented in base). The compiler will execute the code in the constructor then. After the Base part has completely been constructed, construction of the Derived element part starts. The compiler will change the virtual table so that the entry for f() points to Derived::f().

If you try calling the method f() while still constructing Base, the entry in the virtual method table is still null and the application crashes.

David Rodríguez - dribeas
A: 

To call a virutal function function you need to call via a pointer or a reference.

void ClassA::SomeFunction()
{
    VirtualFunction();       // Call ClassA::VirtualFunction

    this->VirtualFunction(); // Call Via the virtual dispatch mechanism
                             // So in this case call ClassB::VirtualFunction
}

You need to be able to distinguish the two different types of call otherwise the classA::VirtualFunction() becomes inaccessible when it is overridden.

As pointed out by others if you want to make the base class version abstract then use the = 0 rather than {}

class A
{
    virtual void VirtualFunction() =0;
....

But sometimes it is legitimate to have an empty definition. This will depend on your exact usage.

Martin York