samedi 19 avril 2014

c ++ - appel à la méthode virtuelle correcte à l'aide du pointeur de fonction membre - Stack Overflow


In the example below, where I tried to reduce the problem to its minimal, there are 4 classes A,B,C,D., which form an inheritance hierarchy


When the program starts, an object d from class D is created and the test method of the D class is called. This method in turns calls the caller method of the C class. This method tries to use member function pointer to call the correct f method. In this case it should call the f method associated to class D but it calls the one associated to class B.


How come ?


class A {
public:
virtual void f() = 0;
};

class B : public A{
public:
virtual void f() { cout << "IN B" << endl;}
};

class C : public B{
public:
virtual void f() { B::f(); cout << "IN C" << endl; }
virtual void caller(){
void (A::*cb)() = NULL;
cb = &A::f;
(this->*cb)();
}
};

class D : public C{
public:
virtual void f() { C::f(); cout << "IN D" << endl; }
void test(){
caller();
}
};

int main(){
D d;
d.test(); // Why does this prints only "IN B"
return 0;
}

UPDATE : The code actually works, the problem had nothing to due with the presented code and seemed to come from a version mismatch between the library providing class A,B,C and the one providing class D.




You sure it prints only "IN B"? I compile it on MSVC2012, I got


IN B
IN C
IN D

What's more, your original code does not compile on VS2012, at least not before I add public: to every class. e.g.:


class C : public B{
public: // <--- here
virtual void f() { B::f(); cout << "IN C" << endl; }
virtual void caller(){
void (A::*cb)() = NULL;
cb = &A::f;
(this->*cb)();
}
};



It prints


IN B
IN C
IN D

So, the problem is somewhere else.




it works. add public: declaration. also warning about different behavior of overloading and virtualisation. best approach is to use pointer or reference.


class A {
public:
virtual void f() = 0;
};

class B : public A{
public:
virtual void f() { std::cout << "IN B" << std::endl;}
};

class C : public B{
public:
virtual void f() { B::f(); std::cout << "IN C" << std::endl; }
virtual void caller(){
void (A::*cb)() = NULL;
cb = &A::f;
(this->*cb)();
}
};

class D : public C{
public:
virtual void f() { C::f(); std::cout << "IN D" << std::endl; }
void test(){
caller();
}
};

output:



IN B
IN C
IN D




In the example below, where I tried to reduce the problem to its minimal, there are 4 classes A,B,C,D., which form an inheritance hierarchy


When the program starts, an object d from class D is created and the test method of the D class is called. This method in turns calls the caller method of the C class. This method tries to use member function pointer to call the correct f method. In this case it should call the f method associated to class D but it calls the one associated to class B.


How come ?


class A {
public:
virtual void f() = 0;
};

class B : public A{
public:
virtual void f() { cout << "IN B" << endl;}
};

class C : public B{
public:
virtual void f() { B::f(); cout << "IN C" << endl; }
virtual void caller(){
void (A::*cb)() = NULL;
cb = &A::f;
(this->*cb)();
}
};

class D : public C{
public:
virtual void f() { C::f(); cout << "IN D" << endl; }
void test(){
caller();
}
};

int main(){
D d;
d.test(); // Why does this prints only "IN B"
return 0;
}

UPDATE : The code actually works, the problem had nothing to due with the presented code and seemed to come from a version mismatch between the library providing class A,B,C and the one providing class D.



You sure it prints only "IN B"? I compile it on MSVC2012, I got


IN B
IN C
IN D

What's more, your original code does not compile on VS2012, at least not before I add public: to every class. e.g.:


class C : public B{
public: // <--- here
virtual void f() { B::f(); cout << "IN C" << endl; }
virtual void caller(){
void (A::*cb)() = NULL;
cb = &A::f;
(this->*cb)();
}
};


It prints


IN B
IN C
IN D

So, the problem is somewhere else.



it works. add public: declaration. also warning about different behavior of overloading and virtualisation. best approach is to use pointer or reference.


class A {
public:
virtual void f() = 0;
};

class B : public A{
public:
virtual void f() { std::cout << "IN B" << std::endl;}
};

class C : public B{
public:
virtual void f() { B::f(); std::cout << "IN C" << std::endl; }
virtual void caller(){
void (A::*cb)() = NULL;
cb = &A::f;
(this->*cb)();
}
};

class D : public C{
public:
virtual void f() { C::f(); std::cout << "IN D" << std::endl; }
void test(){
caller();
}
};

output:



IN B
IN C
IN D



0 commentaires:

Enregistrer un commentaire