14

I was shocked today by the fact that this code snippet has an ambiguous name reference:

class A
{
private:
    typedef int Type;
};

class B
{
public:
    typedef int Type;
};

class D : A, B
{
    Type value;//error: reference to 'Type' is ambiguous
};

Hmm! Imagine you are the author of class A and your class has already been used everywhere by different people and different projects. One day you decide to rewrite your A class. Doesn't this mean that you cannot use any new (even private) name in your new class without breaking others' code?

What is the convention here?

zwhconst
  • 1,352
  • 9
  • 19
  • Similar questions: https://stackoverflow.com/q/5445299/1025391 , https://stackoverflow.com/q/37206557/1025391 – moooeeeep May 07 '20 at 06:39
  • 5
    pimpl idiom, so you no longer have to change private interface. – Jarod42 May 07 '20 at 08:24
  • The semantic meaning of C++ programs is not affected by `public/private` declarations. But the *legality* of them is. If it compiled the first time, changing `private` to `public` should not break it. – user207421 May 07 '20 at 09:54

3 Answers3

2

Yes you are right. Using the current format/logic/coding style might break others' code if you decide to make changes later. Try to use PIMPL or fully qualify symbols. You're example is a good one of why it's not a good idea to not use fully qualify symbols. It's the same issue with code like:

using namespace std;

The line of code above could break a lot of stuff.

0

As @Jarod42 mentioned it needs to follow pimpl idiom (pointer to implementation) to separate interface and implementation:

A.h

#include <memory>

class A
{
public:    
    A(); 
    ~A();     
private:
    class AImpl; 
    std::unique_ptr<AImpl> pimpl;
};

A.cpp

#include "A.h"

class A::AImpl 
{
private:
    typedef int Type;

    /* .. */
};

A::A(): pimpl(new AImpl)
{
}

A::~A() = default;

main.cpp

#include "A.h"

class B
{
public:
    typedef int Type;
};

class D : A, B
{
    Type value;
};
vladimir
  • 13,428
  • 2
  • 44
  • 70
0

I see no issue here, it's not because it's private that the symbol does not exists. If you try to access a private member the compiler tells you that you can't access it, not that does not exists.

Also, I would say it's a bad practise to use multiple inheritence and not fully qualify symbols.

class D : A, B
{
    B::Type value;
};
Nop
  • 151
  • 1
  • 5