Does a pointer to a virtual function still get invoked virtually? - c++

Will a function pointer to a class member function which is declared virtual be valid?
class A {
public:
virtual void function(int param){ ... };
}
class B : public A {
virtual void function(int param){ ... };
}
//impl :
B b;
A* a = (A*)&b;
typedef void (A::*FP)(int param);
FP funcPtr = &A::function;
(a->*(funcPtr))(1234);
Will B::function be called?

Yes. Valid code to test on codepad or ideone :
class A {
public:
virtual void function(int param){
printf("A:function\n");
};
};
class B : public A {
public:
virtual void function(int param){
printf("B:function\n");
};
};
typedef void (A::*FP)(int param);
int main(void)
{
//impl :
B b;
A* a = (A*)&b;
FP funcPtr = &A::function;
(a->*(funcPtr))(1234);
}

Yes. It also works with virtual inheritance.

The function will be called, as you just try to invoke inherited function.

The best test for that thing is to make the methods in the class A a pure virtual method. In both cases (with or without pure virtual methods), B::function will be called.

Related

Is it possible to unhide only specific overloaded method of Base class

#include <iostream>
class B
{
public:
virtual void f() {std::cout<<"Fi";}
virtual void f(int) {std::cout<<"GI";}
};
class A : public B
{
public:
void f(double) {std::cout<<"HI";}
using B::f;//but I want to use only f(), not f(int)
};
int main () {
A a;
a.f();
a.f(10);
return 0;
}
Is it possible in derived class A unhide only f() overload? So a.f(10); would call A::f(double)
You can replace the using statement with a function that calls the base class method:
void f() { B::f(); }
For what you are attempting, make A use protected or private inheritance instead so B's methods are not public in A. Then A can declare its own methods that call B's methods internally.
#include <iostream>
class B
{
public:
virtual void f() {std::cout<<"Fi";}
virtual void f(int) {std::cout<<"GI";}
};
class A : protected B
{
public:
void f(double) {std::cout<<"HI";}
void f() { B::f(); }
};
int main () {
A a;
a.f();
a.f(10);
return 0;
}
Output:
FiHI
Live Demo

How to call a derived class' virtual function from the base class in C++

I have:
class A
{
public:
virtual some_type foo();
protected:
virtual some_type bar();
}
class B : public A
{
protected:
some_type bar() override;
}
// std::shared_ptr<B> b_ptr;
b_ptr->foo();
Where A::foo calls bar. For some reason that I cannot seem to understand, A::bar is being called insted of B::bar. Is there any way to ensure B::bar is called instead?
EDIT:
some_type A::foo() {
this->bar();
}
EDIT 2:
Class was instantiated as A, and then cast to B, hence the shared pointer to B was invalid.
It depends.
If foo() calls bar() in this way:
some_type foo(){ A::bar(); }
This is compile time binding, and so the compiler will bind that call to A::bar() even if the dynamic type is B.
Instead, if foo() calls bar() in this way:
some_type foo(){ this->bar(); /*or just bar(), same thing*/}
Then because bar() is virtual, the binding will be resolved at runtime, and so it will call the bar() function for the dynamic type, thus B::bar().
So this code:
class A
{
public:
virtual void foo(){this->bar();};
protected:
virtual void bar(){cout<<"A";};
};
class B : public A
{
protected:
void bar() override{cout<<"B";};
};
int main() {
std::shared_ptr<B> b_ptr(new B);
b_ptr->foo(); // B
}
Will print B, but this code:
class A
{
public:
virtual void foo(){A::bar();};
protected:
virtual void bar(){cout<<"A";};
};
class B : public A
{
protected:
void bar() override{cout<<"B";};
};
int main() {
std::shared_ptr<B> b_ptr(new B);
b_ptr->foo(); // A
}
will print A

Multiple inheritance in c++ using abstract base classes [duplicate]

I tried this code:
class A
{
virtual void foo() = 0;
};
class B
{
virtual void foo() = 0;
};
class C : public A, public B
{
//virtual void A::foo(){}
//virtual void B::foo(){}
virtual void A::foo();
virtual void B::foo();
};
void C::A::foo(){}
void C::B::foo(){}
int main()
{
C c;
return 0;
}
It is OK when using the commented part, but when I try to write the definitions outside the class declaration, the compiler reports errors.
I am using the MSVC11 compiler, does anyone know how to write this?
I need to move the code into the cpp file.
Thank you~~
A function overrides a virtual function of a base class based on the name and parameter types (see below). Therefore, your class C has two virtual functions foo, one inherited from each A and B. But a function void C::foo() overrides both:
[class.virtual]/2
If a virtual member function vf is declared in a class Base and in a class Derived, derived directly or indirectly from Base, a member function vf with the same name, parameter-type-list, cv-qualification, and ref-qualifier (or absence of same) as Base::vf is declared, then Derived::vf is also virtual (whether or not it is so declared) and it overrides Base::vf.
As I already stated in the comments, [dcl.meaning]/1 forbids the use of a qualified-id in the declaration of a (member) function:
When the declarator-id is qualified, the declaration shall refer to a previously declared member of the class or namespace to which the qualifier refers [...]"
Therefore any virtual void X::foo(); is illegal as a declaration inside C.
The code
class C : public A, public B
{
virtual void foo();
};
is the only way AFAIK to override foo, and it will override both A::foo and B::foo. There is no way to have two different overrides for A::foo and B::foo with different behaviour other than by introducing another layer of inheritance:
#include <iostream>
struct A
{
virtual void foo() = 0;
};
struct B
{
virtual void foo() = 0;
};
struct CA : A
{
virtual void foo() { std::cout << "A" << std::endl; }
};
struct CB : B
{
virtual void foo() { std::cout << "B" << std::endl; }
};
struct C : CA, CB {};
int main() {
C c;
//c.foo(); // ambiguous
A& a = c;
a.foo();
B& b = c;
b.foo();
}
You've got just one virtual function foo:
class A {
virtual void foo() = 0;
};
class B {
virtual void foo() = 0;
};
class C : public A, public B {
virtual void foo();
};
void C::foo(){}
void C::A::foo(){}
void C::B::foo(){};
int main() {
C c;
return 0;
}
I stepped into the same problem and accidentially opened a second thread. Sorry for that. One way that worked for me was to solve it without multiple inheritance.
#include <stdio.h>
class A
{
public:
virtual void foo(void) = 0;
};
class B
{
public:
virtual void foo(void) = 0;
};
class C
{
class IA: public A
{
virtual void foo(void)
{
printf("IA::foo()\r\n");
}
};
class IB: public B
{
virtual void foo(void)
{
printf("IB::foo()\r\n");
}
};
IA m_A;
IB m_B;
public:
A* GetA(void)
{
return(&m_A);
}
B* GetB(void)
{
return(&m_B);
}
};
The trick is to define classes derived from the interfaces (A and B) as local classes (IA and IB) instead of using multiple inheritance. Furthermore this approach also opens the option to have multiple realizations of each interface if desired which would not be possible using multiple inheritance.
The local classes IA and IB can be easily given access to class C, so the implementations of both interfaces IA and IB can share data.
Access of each interface can be done as follows:
main()
{
C test;
test.GetA()->foo();
test.GetB()->foo();
}
... and there is no ambiguity regarding the foo method any more.
You can resolve this ambiguity with different function parameters.
In real-world code, such virtual functions do something, so they usually already have either:
different parameters in A and B, or
different return values in A and B that you can turn into [out] parameters for the sake of solving this inheritance problem; otherwise
you need to add some tag parameters, which the optimizer will throw away.
(In my own code I usually find myself in case (1), sometimes in (2), never so far in (3).)
Your example is case (3) and would look like this:
class A
{
public:
struct tag_a { };
virtual void foo(tag_a) = 0;
};
class B
{
public:
struct tag_b { };
virtual void foo(tag_b) = 0;
};
class C : public A, public B
{
void foo(tag_a) override;
void foo(tag_b) override;
};
A slight improvement over adigostin's solution:
#include <iostream>
struct A {
virtual void foo() = 0;
};
struct B {
virtual void foo() = 0;
};
template <class T> struct Tagger : T {
struct tag {};
void foo() final { foo({}); }
virtual void foo(tag) = 0;
};
using A2 = Tagger<A>;
using B2 = Tagger<B>;
struct C : public A2, public B2 {
void foo(A2::tag) override { std::cout << "A" << std::endl; }
void foo(B2::tag) override { std::cout << "B" << std::endl; }
};
int main() {
C c;
A* pa = &c;
B* pb = &c;
pa->foo(); // A
pb->foo(); // B
return 0;
}
Assuming that the base classes A and B are given and cannot be modified.

base class pointer, invoke method based on derived type

I understand that the following code doesn't work -- can't convert base to foo.
Is there something I can do, or some pattern to employ which would get me close the behavior I'm trying to achieve in the code below? IOW, if I have a base class pointer to a derived type, how can I invoke a specific method that matches the derived type (not the base type)?
What patterns might I use? I looked into Curiously Recursive (or recurring) Template Pattern, however this imposed other limitations itself.
class base {};
class foo : public base {};
void method(const foo& f){}
int main(){
base* b = new foo();
method(*b);
}
The easiest way is probably to just make method() a virtual member function on foo:
class base {
public:
virtual void method() const = 0;
};
class foo : public base {
public:
void method() const override { }
};
int main(){
foo f;
base* b = &f;
b->method();
}
But if for some reason that is not possible (perhaps you don't have access to method() or perhaps you want to keep the logic in method() separate from foo) you could use a simplified version of the Visitor Pattern.
The visitor pattern relies on all the classes in your hierarchy having a virtual function to dispatch based on class type.
In your case you don't need double-dispatch so you don't actually need the visitor object and can just call your method function directly from a virtual dispatch function:
class base {
public:
virtual void dispatch() const = 0;
};
class foo : public base {
public:
void dispatch() const override;
};
void method(const foo& f){}
void foo::dispatch() const {
method(*this);
}
int main(){
foo f;
base* b = &f;
b->dispatch();
}
You have to remember that in most contexts the compiler doesn't know that your base pointer is actually of type foo.
Use virtual functions to solve these kinds of problems:
class base {
public:
virtual void func() const { /* A */ }
};
class foo : public base {
public:
void func() const override { /* B */ }
};
void method(const base& f) {
f.func();
}
int main(){
base* b = new foo();
method(*b);
}
Now, depending on the actual type of f, either A or B code will be executed in method.

Inherited method with different type

i have something like this
class A {
virtual void doBla(A *a) = 0;
};
class B : public A {
virtual void doBla(B *b) { // do stuff ;};
};
and i want to do something like
A* a = new B();
B* b = new B();
a->doBla(b);
or: all children of A are supposed to have a method doBla which takes a parameter of the type of the child. Hope you get my problem and hope someone can help me or convince me that this is bad style :)
edit: added virtual to the methods
You cannot overload functions across base/child classes, and doBla member function of class A must be public if you want to call it from outside:
class A {
public:
virtual void doBla(A *a) = 0;
};
class B : public A {
virtual void doBla(A *a) { /*do stuff*/ }
};
Edit: Note that the declaration of doBla function is similar in A and B classes.
This is impossible as it stands - a doesn't have a doBla(B* b) function, so when you try to call it on the a instance the compiler can't guarantee in any way that function actually exists, and it doesn't know how to look it up. That's an error or ten.
What you might be looking for is double dispatch.
class A {
public:
virtual void doBla(A* a) { a->doBla_impl(this); }
private:
virtual void doBla_impl(A* a);
virtual void doBla_impl(B* b);
// etc
};
class B : public A {
public:
virtual void doBla(A* a) { a->doBla_impl(this); }
private:
virtual void doBla_impl(A* a);
virtual void doBla_impl(B* b);
// etc
};
The trouble with this is that you have to know all the derived types in the base class, which is not always possible or feasible.