2

Couldn't the diamond problem be resolved just by using the first inherited declaration found? I mean,

public class A {
    public virtual int getInt();
};

public class B : public A {
    public int getInt() {return 6;}
};

public class C : public A {
    public int getInt() {return 7;}
};

public class D: public B, public C {};

for class D, since B is listed first, couldn't we just by default (when it's ambiguous) use B::getInt() if D::getInt() is called? Kind of how the PATH environment variable works in UNIX and other OS's; if two things exist with the same name in different locations in the PATH variable, then the first location shall be used by default (unless otherwise qualified).

Edit: by 'first' inherited declaration found I mean according to simple left-to-right depth-first order

Edit#2: Just updated the above implementation to be more diamond-like.

ManRow
  • 1,563
  • 4
  • 21
  • 40
  • 5
    there is no diamond problem here, looks like plain old multiple-inheritance – Nim Jul 15 '11 at 08:25
  • 2
    also, what if someone accidentally changed the order to `B` `A` `C`? Or derived using that order in some other class - it's very fragile.. – Nim Jul 15 '11 at 08:26
  • 1
    Isn't the underlying issue here that any virtual member in A could have different implementations in B or C and that there's no way to resolve those differences in D, as that would pretty much require that the compiler knew exactly what you wanted to get done (which would defeat the purpose of programmers). – John Leidegren Jul 15 '11 at 08:29
  • Resolving ambiguities by arbitrarily guessing what the programmer meant is likely to result in code that doesn't behave as the programmer intended. Forcing the programmer to explicitly state the intended behaviour leaves less room for error. – Mike Seymour Jul 15 '11 at 10:35

2 Answers2

4

It's a very buggy solution. Think what will happen in the following case:

public class A {
    public int getInt() {return 5;}
    public float getFloat() {return 5.0;}
};

public class B {
    public int getInt() {return 6;}
    public float getFloat() {return 6.0;}
};

public class C {
    public int getInt() {return 7;}
    public float getFloat() {return 7.0;}
};

public class D: public A, public B, public C {}

Suppose that one will want D::getInt to return 5 while another developer wants D::getFloat to return 7.0 (thus, different functions resolved to different ancestors). The second developer will change the order of inheritance and a bug will creep in all code paths depending on getInt.

Mihai Maruseac
  • 20,967
  • 7
  • 57
  • 109
  • True, but what if that particular developer group adopts an "**ironclad** coding practice": "DON'T NEVER change the order of inherited classes! (once they are specified)" ? Are there edge cases even if this rule is *always* followed? – ManRow Jul 15 '11 at 08:40
  • 3
    It's not enforceable. Some day, while desperately trying to fix the bug assigned to him, a developer will do this. And now, he'll have two bugs on the eve of a deadline. – Mihai Maruseac Jul 15 '11 at 08:45
  • So other than humans beings != ironclads (@Nim, true indeed!), default left-to-right depth first resolution should otherwise work without problems? – ManRow Jul 15 '11 at 08:56
  • No, you can have two methods or more involved. And some of they might need other resolution order – Mihai Maruseac Jul 15 '11 at 09:03
  • But wouldn't left-to-right depth first resolution order unambiguously resolve the method involved? Also, if someone specifically wanted a different resolution order, couldn't they just instead qualify (with the superclass name) the desired method to be invoked? – ManRow Jul 15 '11 at 09:13
  • In simple projects it is easy to do this. But in projects with a big codebase the situation is different – Mihai Maruseac Jul 15 '11 at 09:21
  • "The second developer will change the order of inheritance": he won't do this since he knows "left-to-right depth first resolution" rule, but will simply define `D::getFloat` to return whatever he wants. – Liviu Jan 04 '14 at 01:09
  • Happened to projects I was involved twice. – Mihai Maruseac Jan 04 '14 at 03:42
0

This is not a diamond problem. C++ compiler is specific about all its syntax, if there is any ambiguity it will always throw error.

Here your A::getInt(), B::getInt() and C::getInt() are ambiguous when you call simply d.getInt().

Edit:

In your edited question, still compiler doesn't evaluate from the inheritance, because some programmers may really need to have different copies of A==> 1st via class B and 2nd via class C. Note that so called diamond problem is a problem characterized by humans. For C++ compiler, it's just one more pattern.

In C++ philosophy, you are not restricted to only one paradigm or pattern. You can choose to have multiple inheritance of your choice.

iammilind
  • 68,093
  • 33
  • 169
  • 336