Short answer: Inheritance is like a Matryoshka doll, and every class fully contains all of its base classes (if any).
Long answer: When a class inherits from one or more other classes, the derived class contains its parent class(es), which in turn contain their parent class(es), until you reach the least-derived class(es) (the class(es) which have no parent classes of their own).  So, for example, with this setup:
class A {};
class B : public A {};
class C : public A {};
class D : public B, public C {};
class E : public D {};
E contains a D, which contains a B (which contains an A) and a C (which contains another A); it looks something like this (generated with MSVC, using compiler option /d1reportSingleClassLayoutE in an online x64 environment).
class E size(1):
        +---
        | +--- (base class D)
        | | +--- (base class B)
        | | | +--- (base class A)
        | | | +---
        | | +---
        | | +--- (base class C)
        | | | +--- (base class A)
        | | | +---
        | | +---
        | +---
        +---
Note that this analogy is slightly off for virtual base classes, which tend to be located immediately after the most-derived class' "main body" (for lack of a better term; the memory allocated to all non-virtual base classes and data members) in memory.
class A {};
class B : public virtual A {};
class C : public virtual A {};
class D : public B, public C {};
class E : public D {};
E contains a D, which contains a B and a C.  E has a single instance of A superglued to its back.
class E size(16):
        +---
        | +--- (base class D)
        | | +--- (base class B)
 0      | | | {vbptr}
        | | +---
        | | +--- (base class C)
 8      | | | {vbptr}
        | | +---
        | +---
        +---
        +--- (virtual base A)
        +---
As each derived class contains its entire inheritance hierarchy, it also contains all variables declared in any of its base classes.
class A { private: int a; protected: int b; public: int c; };
class B { public: int d; };
class C : public A, public B { protected: int e; };
class D : public C {};
static_assert(sizeof(C) == sizeof(A) + sizeof(B) + sizeof(int), "Size mismatch.");
static_assert(sizeof(D) == sizeof(C),                           "Size mismatch.");
static_assert(sizeof(D) == sizeof(int) * 5,                     "Size mismatch.");
D contains C, which contains A (which contains 3 ints), B (which contains an int), and an int.  Neither Clang, GCC, or MSVC will emit a Size mismatch. error.  Using /d1reportSingleClassLayoutD...
class D size(20):
        +---
        | +--- (base class C)
        | | +--- (base class A)
 0      | | | a
 4      | | | b
 8      | | | c
        | | +---
        | | +--- (base class B)
12      | | | d
        | | +---
16      | | e
        | +---
        +---
As such, access specifiers don't actually affect what is or isn't inherited.  What they do affect, however, is what's visible to the derived class.
- privatemembers are only visible in the class where they're declared.- ais visible in- A, but not in- Cor- D
- protectedmembers are visible throughout the inheritance hierarchy, after being encountered.- bis visible in- A,- C, and- D(but not in- B, since it doesn't inherit from- A).- eis visible in- Cand- D.
- publicmembers are laid bare for the world to see.- cand- dare visible everywhere.
All members declared in a class can see any member that is visible to their containing class.  Using your example, A::displayA() can always see A::a, even when called on an instance of derived class B; however, if B declares a member displayA() that hides A::displayA(), then B::displayA() won't be able to see A::a, and would have to rely on public or protected members of A if it wanted to work with A::a.
class A {
    int a;
  public:
    void displayA() { std::cout << "A::a " << a << std::endl; }
};
class B : public A {
  public:
    // Will emit some variation on "A::a is private, you can't access it here."
    // Note that no compiler will claim that it doesn't exist.
    // void displayA() { std::cout << "A::a " << a << std::endl; }
    // This works, though, since it goes through A::displayA(), which can see A::a.
    void displayA() { return A::displayA(); }
};