Say we have a class inheriting from two base classes (multiple inheritance). Base class A is abstract, declaring a pure virtual function foo, the other base class B declares and implements a function foo of the very same signature.
struct A
{
virtual void foo(int i) = 0;
};
struct B
{
virtual void foo(int i) {}
};
struct C : public A, public B {};
I want to use the implementation of foo from base class B in my derived class C. However, if I do not implement the function foo a second time in my derived class C, I cannot instantiate any object of it (it remains abstract). Virtual inheritance does not help here as expected (class A and class B have no common base class).
I wonder if there is a way to "import" the implementation of foo from class B into class C in order not to have to repeat the same code.
Above example is of course contrived. The reason I want implement foo in class B is that I want to derive class D : public B and use class Bs implementation of foo. I know that inheritance is not (primarily) intended for code reuse, but I'd still like to use it in that way.
In java, your sample code works. In C++ it doesn't. A subtle difference between those languages.
Your best option in C++ is to define C::foo() by forwarding to B::foo():
struct C : public A, public B
{
virtual void foo(int i) { B::foo(i); }
};
Related
Suppose i have three classes A, B and C. class B inherits from class A and the inheritance is private whereas class C inherits from B and the inheritance is public. Now class A has a protected function which class C wants to access. So, what must be done in class B to make that protected function available to class C.
Here is the link to the code : http://pastebin.com/9E2sLZzj
The "using" keyword makes a member of an inherited class visible, and resolvable, in the scope of its subclass. So, to make the privately-inherited member available to B's subclasses:
class A {
protected:
void foo() {}
};
class B : private A {
protected:
using A::foo;
};
class C : public B {
void bar()
{
foo();
}
};
Okay i got the solution
This code fragment worked after inserting it into Class B.
int get(){
return A::get();
}
Not sure what it does though
Consider the following code:
class A {
};
class B : public A {
};
class C : public B{
public:
C() : A() {} // ERROR, A is not a direct base of B
};
In this case GCC (4.8.1, C++99) gives me the correct error (I understand this behavior):
prog.cpp:12:8: error: type ‘a’ is not a direct base of ‘c’
However if the inheritance between b and a is virtual, this does not happen:
class A {
};
class B : virtual public A {
};
class C : public B{
public:
C() : A() {} // OK with virtual inheritance
};
Why does this work?
Is A now considered a direct base to C by the compiler?
In general, because this is how C++ tries to resolve the diamond inheritance problem http://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem (whether or it is a good or bad solution is left as an exercise to the reader).
All inheritance is a combination of an is-a and a has-a relationship...you must instantiate an instance of the parent. If you have the following classes:
class a;
class b : a;
class c : a;
class d : b,c;
Then you've instantiated an a for each b and c. d will not know which a to use.
C++ solves this by allowing virtual inheritance, which is high-overhead inheritance that allows b and c to share the same a if inherited in d (it is much more complicated than that, but you can read up on that on your own).
The most derived type in the chain needs to be able to override the instantiation of the shared class to control disparities in the way that the shared class is inherited in the parent classes. Take the following example:
class a {int x; public: a(int xx) {x=xx;} int get_x() {return x;}};
class b : public virtual a { public: b(): a(10){}};
class c : public virtual a { public: c(): a(15){}};
class d : public virtual b, public virtual c {public: d() : a (20) {}};
int main() {
d dd;
std::cout << dd.get_x() << std::endl;//20, d's constructor "wins"
return 0;
}
If d did not define what a was instantiated as, it would have definitions for conflicting instantiations (from b and c). C++ handles this by forcing the most derived class in the inheritance chain to instantiate all parent classes (the above would barf if d did NOT explicitly instantiate a, though if a supplied a default constructor that could be implicitly used) and ignoring all parent instantiations.
Why does this work?
According to the standard (10.1.4 in the FIDS), "for each distinct baseclass that is specified virtual, the most derived object shall contain a single base class subobject of that type".
Virtual base is shared between all classes that derive from it for the instance of the object. Since a constructor may only be called once for a given instaniation of an object, you have to explicitly call the constructor in the most derived class because the compiler doesn't know how many classes share the virtual base. This is because the compiler will start from the most base class's constructor and work to the most derived class. Classes that inherit from a virtual base class directly, will not, by the standard, call their virtual base classes constructor, so it must be called explicitly.
From N3337, 12.6.2
Initializing bases and members
In the definition of a constructor for a class, initializers for direct and virtual base subobjects and non-static data members can be specified by a ctor-initializer, which has the form
Perhaps someone who has better version of Standard can verify this.
Say we have this:
class A
{
public:
virtual void foo() = 0;
};
class B: public A
{
public:
virtual void foo() = 0;
};
The compiler throws no error, I guess its because B is also an abstract class and as such it does not have to implement foo from A.
But what does such a construct mean?
1) Does foo from B hide foo from A?
2) The first class which inherits from B and is not an abstract class, does it have to provide two implementations like:
class C: public B
{
public:
virtual void A::foo() {};
virtual void B::foo() {};
};
The compiler only complains if the implementation of B::foo() is missing, but it does not complain about a missing A::foo().
All in all: is this a way to hide pure virtual methods?
When you first declare:
class A
{
public:
virtual void foo() = 0;
};
you are declaring the method foo public, virtual and pure. When a class contains at least a pure method it's called abstract. What does it mean? It means that the class cannot be instantiated because it needs the pure methods implementations.
You can obviously inherit from an abstract class (I'd say that you are forced to do that, otherwise what would be the need of an abstract class you are not using, except for providing an interface to inherit from?) and you can also inherit from an abstract class and not implement some or all of the pure methods of the parent class; in this case the child class is abstract as well, which is the case of your class B:
class B: public A
{
public:
virtual void foo() = 0;
};
In B you could easily omit the virtual void foo() = 0; declaration because the definition is already inherited from the base class. In this case class B is an abstract class and therefore cannot be instantiated, just like A.
To answer your questions more directly:
Does foo from B hide foo from A?
No, it does not. They both are declaring a pure method (which is in fact the same method), therefore there's nothing to really hide.
The first class which inherits from B and is not an abstract class, does it have to provide two implementations like the one provided?
No, of course not. As stated above, they are the same method, therefore if class C have to provide an implementation for foo it should just implement foo:
class C: public B
{
public:
virtual void foo() {};
};
0) The compiler throws no error ...
It will throw an error when you try to instantiate an object from A or B which they're abstract. Not when you're inheriting and declaring them.
1) Does foo from B hide foo from A?
No. It overtides A::foo not hides it.
2) The first class which inherits from B and is not an abstract class,
does it have to provide two implementations ...
No. Just override foo and make one implementation for it.
class C : public B
{
public:
virtual void foo()
{
std::cout << "ABCD" << std::endl;
}
};
int main()
{
C c;
A *a = &c;
a->foo(); // Prints ABCD string and proofs B::foo doesn't hide A::foo
}
I compiled your code with gcc 4.5.3, it gave the following error messages:
error: cannot define member function ‘A::foo’ within ‘C’
error: cannot define member function 'B::foo' within 'C'
In you example, both class A and B are abstract classes since foo is pure virtual. They only define that derived class of B should implement the behavior of foo since there is no default behavior to use (if the derived class is not abstract anymore).
Question 1:Does foo from B hide foo from A?
Since foo in B and A has exactly the same name, same signature and foo is virtual in base class, so it is not hiding, it is overriding. FYI: A derived class's function overrides a base class function if the signature is the same and it's declared virtual in the base class. If you call it
through a pointer or a reference to the base class, the function in the
derived class is called. It "overrides" the one in the base class.
Hiding only comes into play if you call a non-virtual function through a
pointer or reference or directly with an object of the derived class. A
derived class' function hides all base class functions with the same name.
Question 2: The first class which inherits from B and is not an abstract class, does it have to provide two implementations
No. You can do the following:
class C: public B
{
public:
virtual void foo()
{
cout << "foo defined in c" <<endl;
}
};
Suppose I have this class hierarchy:
class A {
public:
virtual void foo(Base *b) = 0;
};
class B {
public:
virtual void bar() = 0;
};
class C : public A, public B {
public:
virtual void viz() = 0;
};
class E : public C {
public:
/** Some non-pure virtual functions, does not implement foo */
};
class F : public E {
/** does not implement foo */
}
class G : public E {
/** does not implement foo */
}
Now, I would like to define derived, "templatized" versions of F and G, which declares a method foo(T *s) and where the implementation of foo(Base *s) simply calls foo(T *s) by applying a static_cast.
Moreover, I don't wan to expose the template arguments to A, because users of these interfaces (A, B, C, E) should not be exposed to the template parameters (I'm writing a plugin architecture and user-types that derives a given interface are passed back and forth from plugins to base system).
What I thought was to define this class:
template <typename T>
class GA : public A{
...
}
and to define the "templatized" derivations of F and G like this:
template <typename T>
class GF : public F, public GA {
...
}
the problem is that GF sees two different declarations of foo() (one given by A, the other by GA), so the compiler throws me an error when I try to instantiate GF because foo(Base) is not defined.
How can I solve this?
Why do you need multiple inheritance? Why not just class C : public Impl { ... }?
I think the problem is that Impl inherits class A and class C inherits both Impl and A. This means there will be two instances of class A where first A's foo is implemented by Impl and a seconds one is still pure virtual. Virtual inheritance can solve this problem, for example:
class A {
public:
virtual void foo () = 0;
};
class Impl : virtual public A {
public:
virtual void foo () {}
};
class C
: virtual public A
, public Impl
{
};
I would suggest something different. Declare the function as a pure virtual function, and then just trivially implement it in the derived classes by forwarding the call:
class A {
public:
virtual void foo() = 0;
};
void A::foo() {}
class B : public A {
void foo() { A::foo(); }
};
But that does not mean that you cannot achieve what you are trying to do. If you want to implement that operation in another class and use inheritance, you can do it in two different ways:
Intermediate type:
Implement an intermediate type that provides the functionality, then each derived type can extend either the original A or the intermediate I type:
class I : public A {
public:
void foo() {}
};
class B : public I {}; // inherits the implementation
class C : public A { // needs to provide it's own implementation
void foo() {}
};
Virtual inheritance:
Alternatively you can use virtual inheritance (of the three options I would avoid this). In this way you can create a hierarchy where V inherits virtually from A and provides the implementation. The rest of the classes can either inherit from A directly or inherit from A virtually and also inherit from V. By using virtual inheritance you ensure that there is a single A subobject in your hierarchy:
class V : public virtual A {
public:
void foo() {}
};
class B : public virtual A, V { // Inheritance from V is a detail, can be private
// no need to provide foo
};
Note that this approach is overkill for this particular limited problem, and that it has side effects (the layout of the objects will be different and they will be slightly bigger in size). Again, unless you want to mix and match functions from different sibling classes, I would avoid this.
What was wrong in your code
The problem in your code is that you are inheriting from A multiple times, one through D and another directly. While in the path from D the virtual function is no longer pure, in the direct path from A the virtual function is still undefined.
That also causes the second issue in the error message: ambiguity. Because there are two A subobjects, when you try to call foo on the most derived type, the compiler cannot figure out on which of the two A subobjects you want to execute the request. The same type of ambiguity problems would arise if you tried to cast from the most derived type into A directly, as the compiler would not know to which A you want to refer.
Impl does not implement A's method in D and C, it's a completely different base.
You should derive Impl from A, then derive every class of that subset from Impl instead of A.
If you want to inherit from both the A and Impl, then you need to use virtual inheritance.
Edit:
See #Vlad's answer for more details.
Hello :) i would like to ask, if it's posible to make something like this:
i have base class (parent) A and three other classes (childs) B C D
in class A, i have virtual functions, that's ok.
but what if i need a virtual class ?
class A
{
public:
virtual int func1()=0;
virtual int func2()=0;
virtual class AB; // !!!!???
};
class B
{
public:
int func1();
int func2();
class AB
{
public:
....
};
};
classes B C D are same as class B. Now, i would like to create class instance and it should automaticly "redirect" class to instance of B or C D etc like functions.
is it possible ? i hope, you understand :) Thank you very much for answer.
This is fundamentally impossible. A virtual function call is determined at runtime. A class changes the behaviour of the program at compile-time. You can't make a compile-time determination at runtime unless runtime and compiletime are the same time, i.e. using a JIT or other dynamic code generators. In standard C++, this is impossible.
What you CAN do is have a base class AB, with a virtual function that creates a class that is guaranteed to inherit from this base class, and then return a pointer to that.