Refer base class members from derived class
Asked Answered
G

5

7
class A {
    public:
        void fa() {
        }
    };

class B : public A{
public:
    void fb() {
    }
};

class C : public A, public B {
public:
    void fc() {
        //call A::fa(), not B::A::fa();
    }
};

How to call A::fa() from C::fc() function.

GCC warns withdirect base A inaccessible in C due to ambiguity, does this mean there is no direct way to refer base class members?

Gurias answered 27/6, 2011 at 5:4 Comment(5)
In your present code class B doesn't inherit class A. Have you put the updated code ?Wirework
My mistake :), now it is fixedGurias
Do you want there to be one A base class subobject for C or two A base class subobjects (one from C deriving from A and one from B deriving from A)? Right now you have two, which may or may not be your intent.Washedout
I want two A base classes, and I want to call the first A's fa() member functionGurias
You should edit your question to include this information, otherwise you will have a bunch of answer proposing virtual inheritance.Romona
W
8

One option would be to create a stub class that you can use for casting to the right base class subobject:

struct A {
    void fa() { }
};

struct B : A {
    void fb() { }
};

// Use a stub class that we can cast through:
struct A_ : A { };

struct C : A_, B {
    void fc() {
        implicit_cast<A_&>(*this).fa();
    }
};

Where implicit_cast is defined as:

template <typename T> struct identity { typedef T type; }

template <typename T>
T implicit_cast(typename identity<T>::type& x) { return x; }
Washedout answered 27/6, 2011 at 5:23 Comment(4)
I admit, I am stumped by the question, and am very interested as to whether there is a way to do this without injecting a stub class into the lattice.Washedout
Using a stub is a nice workaround, I don't think there is any way to achieve this behavior without such trick. That is a limitation of the language I have never considered!Romona
Why are you using an implicit_cast instead of a static_cast? I find an SO post answering my question, but you could perhaps add a little explanation, or a link to some information on that.Romona
@Luc: static_cast is dangerous because it can be used to reverse most of the implicit conversions (notably, it can convert void* to T* where T is an object type). With implicit_cast you can be sure that whatever it does could be done implicitly via the introduction of another variable or reference; e.g., here we could just as easily use A& thisA = *this; thisA.fa();. The implicit_cast code just makes this a bit cleaner. It's also helpful for adding a const-qualifier to a type.Washedout
G
5

I just found the following info from ISO C++ 2003 standard (10.1.3)

A class shall not be specified as a direct base class of a derived class more than once. [Note: a class can be
an indirect base class more than once and can be a direct and an indirect base class. There are limited
things that can be done with such a class. The non-static data members and member functions of the direct
base class cannot be referred to in the scope of the derived class. However, the static members, enumerations
and types can be unambiguously referred to.

It means there is no direct way :(

Gurias answered 27/6, 2011 at 5:37 Comment(0)
D
1

I just compiled you code on codepad.org , putting A::fa() is enough to call fa() from your C::fc() function.

 void fc() {
       A::fa();
    }

The below is the link to codepad with your code.

http://codepad.org/NMFTFRnt

Dympha answered 27/6, 2011 at 5:13 Comment(6)
I don't know what compiler codepad uses, but clang 3.0/133044 and g++ 4.5.1 both reject that.Washedout
@James McNellis : yes, it's more relating to compiler issue not with the language itself.Dympha
It compiles because B does not derive from A in your code.Romona
What do you mean "it's more relating to compiler issue"? I don't think it's a compiler issue; I think the code is invalid.Washedout
The inheritance of B from A was missed, now there will be compiler error :)Gurias
@James McNellis : that was not an issue at all ,@Gurias just missed the line of inheritance of B from A :)Dympha
W
0

You can use virtual inheritance to overcome such problem:

class B : virtual public A {

Now, you can use A::fa() simply in the child class C.

void fc()
{
  fa();
}

However, I generally don't see any practical need to inherit class A again into class C, when B is already publically inheriting A. So, In your case, you can make it simple:

class C : public B {

Edit:

If you want 2 instances for A. then the direct instance which you are intending can be made as an object of C:

class C : public B {
  A obj;

Because, having a directly inherited A will not be usable in anyway. You cannot declare any pointer or reference to it inside the scope of C.

Wirework answered 27/6, 2011 at 5:11 Comment(2)
This is not for practical use, I just want to know is there a way to do this? By the way in case of the virtual inheritance, there will be one A base class, and there will be no any ambiguities.Gurias
@MKo, I have mentioned in my edited answer already. For your case, you don't need to inherit A into C. Also it might prove a bad design at long run.Wirework
A
0

I don't think you can do what you want. There is an ambiguity here: when you say A::fa(), it still doesn't tell the compiler which A object to use. There isn't any way to access class A. That's what the warning is telling you.

This seems like an awfully strange construct, though. Public inheritance should be used for is-a relationships. You are saying that C is-a A twice over? It doesn't make sense. And that suggests that this is either an artificial example that would never come up in practice, or you should reconsider this design.

Austen answered 27/6, 2011 at 5:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.