Hi,

If I static cast an object of a derived class to its base class, the object's virtual methods should be those of the base class. But this doesn't seem to be the case if I call such a virtual method via another method. The following is an extremely simplified version of my code. func3 in class B does not give "A: func1" as ouput, and I don't understand why:

#include <iostream>
using namespace std;

class A {
public:
  virtual void func1() {cout << "A: func1" << endl;}
  void func2() {func1();}
};

class B: public A {
public:
  void func1() {cout << "B: func1" << endl;}
  void func3() {static_cast<A*>(this)->func2();}
};

int main() {
  B b;
  b.func1();
  b.func2();

  // The following gives "B: func1" as output, not "A: func1"
  b.func3();
}

One could do this to get "A: func1" as output:

void func4() {A::func1();}

but this doesn't solve my problem (let's assume I don't want to call func1 any way other than via func2). The only solution I can find that gives "A: func1" as output is:

void func5() {
  A temp = *static_cast<A*>(this);
  temp.func2();
}

but this is very slow and inefficient. Any suggestions? I have tried dynamic_cast and reinterpret_cast. Any explanation of why func 3 doesn't give "A: func1" as output would be particularly appreciated.

Thanks alot in advance for any help.

thelamb commented: Clear explanation, nice 'reproducable code sample' +2
Nick Evan commented: And don't forget the code-tags in first post! Bravo! +12

This is the correct (and beautiful) behavior. When you access a member function through a reference or a pointer of a base class, the derived class's function will be called.
This allows you for instance to store a container of BaseClass* and store many different DerivedClass objects, without having to keep some kind of type-specifier in the base class.

I've never had to call a base virtual function explicitly and I don't really understand why you have a function in B specifically to call another function in A.
According to: http://www.java2s.com/Tutorial/Cpp/0180__Class/Callbasevirtualfunctionexplicitly.htm

This should work(I did not try to compile it):

b.A::func1( ); // Calls the base version

Many thanks thelamb for your reply. The code I gave is a very shortened version of the code I'm using. Without going into details, I don't want to call func1() directly, I want to call func1() via another method. For example, think of func1() as an integrand, and func2() as a numerical integration routine.

What I find strange is that the method

void method_in_B1() {
  A temp = *static_cast<A*>(this);
  temp.func2();
}

in class B *does* gives "A: func1()" as output, but the method

void method_in_B2() {
static_cast<A*>(this)->func2();
}

in class B does *not* give "A: func1()" as output.

Yes that is absolutely correct. As I said, if you call a function through a reference or a pointer you will call the function on the derived class.
If you cast the pointer to a BaseClass, you lose any relation with any derived classes(this is called slicing). Basically "A temp" has no idea that it was cast from a derived class, while "A* temp" will have that 'knowledge'.

What I still don't understand is why this doesn't solve your problem:

void B::func4() { A::func1(); }

I guess I will just have to live with my (incredibly) slow method_in_B2() above.

Your func4 above doesn't work for me as I don't want to call func1() directly other than via func2().

Thanks.

thelamb is correct in his statement. I've modified the code below.

class A {
public:
  virtual void func1() {cout << "A: func1" << endl;}
  void func2() {A::func1();}
};
 
class B: public A {
public:
  void func1() {cout << "B: func1" << endl;}
  void func3() {A::func2();}
};

Personally, I don't see the point in what you're trying to achieve here and I think you have more of a design issue than a development issue =/

(eg. making func1 private and possibly func2 protected? Then func3 calls func2 which calls func1 (private) but again, it's hard to see why something like that is required from what you've given us.)

I agree with everything that you have both said.

Thanks for your suggestion Ketsuekiame, but I don't want to modify func2(), because sometimes I want func2() to call A::func1(), but sometimes I want func2() to call B::func1().

I wonder if there is at least a way to make method_in_B1() above more efficient.

Using static cast is a pretty efficient way of casting.

I think the only alternative method you have is to put some decision making logic in there so that func2 knows which function to call.

Thanks for your help. I already have a solution to my problem (func5 above), I really just wanted to understand from a conceptual point of view why func3 doesn't "work" (i.e. doesn't give "A: func1" as output). I think it is interesting, and a feature of C++ that must be there for a good reason, whatever that may be.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.