11

I am just starting out with gnu-cpp and would like some help. I have come across the ambigutity error while reading and while self-study I came across this idea that static methods of a class should also be affected by the ambiguous diamond problem, but while running the following code ther is no error. Can anyone please explain why?

#include<iostream>
using namespace std;
class Base
{
  public:
  static void display(){cout<<"Static";}
};
class Derived1 : public Base {};
class Derived2 : public Base {};
class Child : public Derived1, Derived2 {};
int main(void)
{
  Child obj;
  obj.display();
}

Thank You for the help and time.

Mudit Singal
  • 133
  • 1
  • 7
  • Duplicate: https://stackoverflow.com/questions/998247/are-static-fields-inherited – iBug Feb 19 '18 at 11:29
  • Also https://stackoverflow.com/questions/515763/how-can-derived-class-inherit-a-static-function-from-base-class – iBug Feb 19 '18 at 11:30
  • Base::display() is a private static method in Base,so it should not be callable in main(). Here's a snippet in Godbolt: https://godbolt.org/g/XpyA2m The default protection for a class is private. You should probably add a "public:" line before the declaration. – Jonathan O'Connor Feb 21 '18 at 10:20
  • Yeah, sorry about that @JonathanO'Connor. Though I did mean the same. Updating it now. – Mudit Singal Feb 22 '18 at 07:26

3 Answers3

14

It's fine according to the lookup rules. You see, when you write member access (obj.display();), the member display is looked up not just in the scope of the class and its base classes. Base class sub-objects are taken into consideration as well.

If the member being looked up is not static, since base class sub-objects are part of the consideration, and you have two sub-objects of the same type, there's an ambiguity in the lookup.

But when they are static, there is no ambiguity. And to make it perfectly clear, the C++ standard even has a (non-normative) example when it describes class member lookup (in the section [class.member.lookup]):

[ Note: A static member, a nested type or an enumerator defined in a base class T can unambiguously be found even if an object has more than one base class subobject of type T. Two base class subobjects share the non-static member subobjects of their common virtual base classes.  — end note ] [ Example:

struct V {
  int v;
};
struct A {
  int a;
  static int   s;
  enum { e };
};
struct B : A, virtual V { };
struct C : A, virtual V { };
struct D : B, C { };

void f(D* pd) {
  pd->v++;          // OK: only one v (virtual)
  pd->s++;          // OK: only one s (static)
  int i = pd->e;    // OK: only one e (enumerator)
  pd->a++;          // error, ambiguous: two as in D
}

 — end example ]

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
4

The Base::display that you get via Derived1, and the Base::Display that you get via Derived2, are literally the same function. With no object context to consider (since they are static) there is no ambiguity here.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
3

Yes. It's inherited because it's a class member.

There's no ambiguity because all that's called with obj.display() is that there's only 1 candidate to be chosen, the ultimate "source" Base::display().

This code, however, generates an error:

class SuperBase {
    public:
    static void hello() { cout << "Super Base" << endl; }
};

class Base1 : public SuperBase {
    public:
    static void foo() { cout << "Base 1" << endl; }
};

class Base2 : public SuperBase {
    public:
    static void foo() { cout << "Base 2" << endl; }
};

class Derived : public Base1, public Base2 {
};

Derived obj;
obj.foo();  // Error: ambiguous resolution
obj.hello();  // No error here
iBug
  • 35,554
  • 7
  • 89
  • 134