Multiple inheritance and virtual functions with differente signature bu same name

Dear experts,
I have the following code which does not compile:

#include <iostream>
using namespace std;

class A
{
public:
virtual int foo(int i) = 0;
};

class B
{
public:
virtual double foo(int i)
{
cout << "B::foo" << endl;
return 0.0;
}
};

class Derived: public A, public B
{
public:
int foo(int i)
{
cout << "Derived::foo" << endl;
return 0;
}
};

int main ()
{
Derived* d = new Derived();
d->foo(0);

return 0;
}

The error message is:
error: virtual function 'foo' has a different return type
('int') than the function it overrides (which has return type 'double')

How can I tell the compiler that Derived::foo is simply the implementation of the virtual member function foo of class A?
Moreover I would like to do so without changing A nor B.

Many thanks for your help.
Kind regards,
- Mauro.
Use an intermediate class C to override A::foo(). Also note that when you call foo, you have to specify whether you want C::foo() or B::foo() because otherwise it's ambiguous:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
using namespace std;

class A
{
  public:
    virtual int foo(int i) = 0;
};

class B
{
  public:
    virtual double foo(int i)
    {
	cout << "B::foo" << endl;
	return 0.0;
    }
};

class C : public A {
public:
    int foo(int i)
    {
	cout << "C::foo" << endl;
	return 0;
    }
};


class Derived:public C, public B
{
};

int
main()
{
    Derived *d = new Derived();
    d->C::foo(0);
    d->B::foo(0);
    return 0;
}

Many thanks for your reply, which actually works pretty well.
I just realized that my example was an oversimplification.
The proper example and problem is this one:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include <iostream>
using namespace std;

class A
{
public:
  virtual int foo(int i) = 0;
  virtual void bar()     = 0;
};

class B: public A
{
public:
  int foo(int i)
  {
    cout << "B::foo" << endl;
    return 0;
  }
  void bar()
  {
    cout << "B::bar" << endl;
  }
};

class C
{
public:
  virtual double foo(int i)
  {
    cout << "C::foo" << endl;
    return 0.0;
  }
};

class D: public A, public C
{
public:
  int foo(int i)
  {
    cout << "D::foo" << endl;
    return 0;
  }
  void bar()
  {
    cout << "D::bar" << endl;
  };
};

int main ()
{
  A* a1 = new B();
  A* a2 = new D();
  
  a1->foo(0);
  a2->foo(0);
  
  return 0;
}


I can't modify class A, nor class B, nor class C. Only D and the main program.
I need to be able in the main program to instantiate the class A as new B or new D and use either B::foo or D::foo

Do you have any suggestion?
Many thanks again.
- Mauro.
Can't you just do what dhayden suggested?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <iostream>
using namespace std;

class A {
public:
  virtual int foo(int i) = 0;
  virtual void bar()     = 0;
};

class B: public A {
public:
  int foo(int i) {cout << "B::foo" << endl; return i;}
  void bar() {cout << "B::bar\n";}
};

class C {
public:
  virtual double foo(int i) {cout << "C::foo\n"; return i;}
};

class X : public A {
public:
  int foo(int i) {cout << "D::foo\n"; return i;}  
};

class D: public X, public C {
public:
  void bar() {cout << "D::bar\n";};
};

int main () {
  A *b = new B(), *d = new D();
  b->foo(0);
  d->foo(0);  
  return 0;
}

Same suggestion as @dhaden suggested before. Add an intermediate class before D.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class PreD : public A
{
public:
  int foo(int i)
  {
    cout << "PreD::foo" << endl;
    return 0;
  }
};

class D: public PreD, public C
{
public:
  void bar()
  {
    cout << "D::bar" << endl;
  };
};
Dear All,
many thanks for you replies.
Again forgive me for stating the previous problems in a too simplified form.

The actual, I think ultimate, problem is the following:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
using namespace std;

class A
{
public:
  virtual int  foo(int i) = 0;
  virtual void bar()      = 0;
};

class B: public A
{
public:
  B(int i)
  {
    ID = i;
  }
  int foo(int i)
  {
    cout << "B::foo: " << this->ID << endl;
    return 0;
  }
  void bar()
  {
    cout << "B::bar" << endl;
  }
private:
  int ID;
};

class C
{
public:
  C(int i)
  {
    ID = i;
  }
  virtual double foo(int i)
  {
    cout << "C::foo" << endl;
    return 0.0;
  }
  int ID;
};

class preD: public A
{
public:
  int foo(int i)
  {
    cout << "preD::foo: " << "_I need to access C::ID_" << endl;
    return 0;
  }
};

class D: public preD, public C
{
public:
  D(int i) : C(i) {};
  // int foo(int i)
  // {
  //   cout << "D::foo" << this->C::ID << endl;
  //   return 0;
  // }
  void bar()
  {
    cout << "D::bar: " << this->C::ID << endl;
  };
};

int main ()
{
  A* a1 = new B(1);
  A* a2 = new D(2);
  
  a1->foo(0);
  a1->bar();
  
  a2->foo(0);
  a2->bar();
  
  return 0;
}


As you can see your solution is totally fine if class preD doesn't need to access anything from class C, but my problem is that preD::foo needs to access something initialized in class C.

I can't modify class A, nor class B, nor class C. Only D, preD, and the main program.
I need to be able in the main program to instantiate the class A as new B or new D, or preD, and use either B::foo or D::foo (or preD::foo)

Many thanks for your help.
Regards,
- Mauro.
This may seem a little bit contrived, but...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
class PreD : public A
{
public:
  int foo(int i)
  {
    cout << "PreD::foo" << endl;
    helperFunction();
    return 0;
  }

protected:
  virtual void helperFunction() = 0;
};

class D: public PreD, public C
{
public:
  void bar()
  {
    cout << "D::bar" << endl;
  };

protected:
  virtual void helperFunction()
  {
    C::foo();
  }

};
my problem is that preD::foo needs to access something initialized in class C.

Make C a member object instead of a base class. If you do that then you don't need class preD at all and you can call C:: foo explicitly:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
#include <iostream>
using namespace std;

class A
{
public:
    virtual int foo(int i) = 0;
    virtual void bar() = 0;
};

class B:public A
{
public:
    B(int i)
    {
	ID = i;
    }
    int foo(int i)
    {
	cout << "B::foo: " << this->ID << endl;
	return 0;
    }
    void bar()
    {
	cout << "B::bar" << endl;
    }
private:
    int ID;
};

class C
{
public:
    C(int i)
    {
	ID = i;
    }
    virtual double foo(int i)
    {
	cout << "C::foo" << endl;
	return 0.0;
    }
    int ID;
};

class D:public A
{
public:
    D(int i) : c(i)
    { };
    int foo(int i)
    {
	cout << "D::foo: C's ID is " << c.ID << endl;
	return 0;
    }
    void bar()
    {
	cout << "D::bar: " << c.ID << endl;
    };
    C c;
};

int
main()
{
    A *a1 = new B(1);
    A *a2 = new D(2);

    a1->foo(0);
    a1->bar();

    a2->foo(0);
    a2->bar();

    return 0;
}

Output:
B::foo: 1
B::bar
D::foo: C's ID is 2
D::bar: 2
Topic archived. No new replies allowed.