Shorthand to specify that a derived class implements all abstract methods? - c++

I find that in some of my code which relies heavily on C++'s polymorphism features, I have a lot of repetitive method declarations.
struct Base
{
virtual void Foo () = 0;
virtual void Bar () = 0;
};
struct DerivedA : public Base
{
void Foo () override;
void Bar () override;
};
struct DerivedB : public Base
{
void Foo () override;
void Bar () override;
};
With a greater number of derived classes like DerivedA and DerivedB, and/or more numerous abstract methods than just Foo and Bar, writing the function signatures in each derived class gets really redundant, and to cut down on entirely repeated code I've started using some macros for convenience but this is probably not a great habit.
My question: Is there any keyword or other syntax feature that I can use in each derived class, that essentially informs the compiler "all abstract methods are overridden for this", instead of typing out all of those methods' signatures?
Concept:
struct DerivedA : public Base
{
concrete;
// ^ Compiler now allows me to instantiate DerivedA and the linker expects
// DerivedA::Foo () and DerivedA::Bar() implementations to exist, just as if
// I had listed every pure virtual function as being overridden explicitly.
};
If this does not exist in C++, out of curiosity are there other languages that have this kind of mechanism, and are there any obvious pitfalls w/ this idea?

Related

Merging abstract and final methods through multiple inheritance

Consider the following program:
#include <stdio.h>
#include <memory>
using namespace std;
class WheeledVehicle {
public:
virtual void drive() const { printf("Default driving implementation."); }
};
class GroundVehicle : public WheeledVehicle {
public:
void drive() const final { WheeledVehicle::drive(); }
};
class DrivableAssaultMachine {
public:
virtual void drive() const = 0;
void fire_cannon();
};
class FighterJet : public DrivableAssaultMachine {
public:
void fly() const { printf("flying my plane.\n"); }
void drive() const override { fly(); }
};
class Tank : public DrivableAssaultMachine, public GroundVehicle {
};
int main(int argc, char **argv) {
make_shared<Tank>()->drive();
return EXIT_SUCCESS;
}
I would like to make this program compile using only modifications to Tank. If I implement drive, then it contradicts the final declaration in GroundVehicle. If I don't implement it, then Tank is abstract and can't be instantiated. Is there some other way to get Tank's inherited implementation of drive() be recognized in the context of inheriting from DrivableAssaultMachine?
EDIT: Renamed everything to provide a more concrete example.
Conceptual flaw:
class FighterJet could not be derived from DrivableAssaultMachine as
DrivableAssaultMachine is derived from class GroundVehicle.
FighterJet are not GroundVehicles.
You should differentiate GroundVehicles and AirVehicles and add: drive and fly as member functions in those and then derive Tank from the first and FighterJet, from the second.
After the n-th Edit:
You've just took under consideration what I've told you and changed the inheritance structure, braking DrivableAssaultMachine from WheeledVehicle
Final Answers:
If I implement drive(), then it contradicts the final declaration in GroundVehicle.
drive() is redundant in FighterJet(as it has fly() available), removing it from there will allow you to override it in Tank.
The virtual drive in DrivableAssaultMachine has nothing to do with the drive() inherited from WheeledVehicle. So there should be ambiguity when try to override it in Tank, as it has as base classes both DrivableAssaultMachine and indirectly WheeledVehicle.
Note: In general your abstract class should provide basic functionality, for example member function: a virtual move() and then the derived classes should wrap it up(override it) and specialize it to their needs, for example: drive() and fly(). Your only tools to specify visibility and accessibility is via the public, private and protected specifier during the definition and the inheritance.
I solved this by creating a diamond hierarchy and using virtual inheritance. Here is a simplified visualization of my hierarchy from the question:
WheeledVehicle
\
DrivableAssaultMachine GroundVehicle
\ /
Tank
Although my feeling is that the compiler should be able to resolve ambiguities and virtualization here, the fact is that it can't. My solution is to fully connect the diamond and use virtual inheritance:
Drivable
/ \
/ WheeledVehicle
/ /
DrivableAssaultMachine GroundVehicle
\ /
Tank
Here is the final program:
#include <stdio.h>
#include <memory>
using namespace std;
class Drivable {
public:
virtual void drive() const = 0;
};
class WheeledVehicle : public virtual Drivable {
public:
virtual void drive() const override { printf("Default driving implementation.\n"); }
};
class GroundVehicle : public WheeledVehicle {
public:
void drive() const final { WheeledVehicle::drive(); }
};
class DrivableAssaultMachine : public virtual Drivable {
public:
void fire_cannon();
};
class Tank : public DrivableAssaultMachine, public GroundVehicle {
};
int main(int argc, char **argv) {
make_shared<Tank>()->drive();
return EXIT_SUCCESS;
}
In general, the workaround appears to be using simple virtual interfaces near the root of your inheritance tree, and combining or complexifying interfaces as you get toward the leaves.
C++ is not Java.
The inheritance and overriding in C++ has to be more explicit than in Java. (I think C++ is right here.)
In C++, two virtual functions declarations foo (with the same signature) are considered homonyms, distinct, unrelated functions unless one declaration overrides the other.
struct B1 {
virtual void foo();
};
struct B2 {
virtual void foo();
};
struct D : B1, B2 {
void bar();
};
D has two inherited declarations of a member function with the same signature, and unqualified calls to foo() within D::bar() would be ambiguous, but the definition of class D is well formed. There is no problem with having potential ambiguities in C++, only ambiguous calls are disallowed.
This means that you can derive from base classes with unrelated homonyms. You just have to avoid ambiguous calls.
Even when both declarations of foo() come from the same class:
struct B {
virtual void foo();
};
struct Left : B {
};
struct Right : B {
};
struct D : Left, Right {
void bar();
};
Both inherited declarations of B::foo() are simply homonyms: they come from the same class, but they in two distinct base classes. C++ lets you have homonyms. The compiler doesn't believe the functions do the same thing or are related in any way other than having the same name, explicit argument list (the arguments inside parentheses), implicit this argument type (of type Base*), and being declared by the same declaration in the source file!
Of course, there is potential ambiguity: if you try to call foo on a derived object, or try to convert (implicitly, or explicitly with static_cast or a C-style cast) a derived pointer to an ambiguous base class pointer.
[Note: some people call that "diamond inheritance" (although the inheritance graph is a tree not a "diamond"), or "dreaded diamond" (it's only dreaded if you don't understand MI in C++) or "diamond of death" (who died?) or "diamond of end of the world" (now I'm making stuff up, but it's only slightly more over the top than "diamond of death"). Seriously, don't freak out people with a potential ambiguity. --end note]
This means that you can derive from base classes with unrelated derivation of the same non virtual base class. You just have to avoid ambiguous calls and ambiguous conversions. (This can happen when two classes derive from the same utility class like refcounted_base.)
In Java, multiple inheritance of classes doesn't exist, but multiple interface inheritance does, and distinct declarations of a given (pure virtual) function are synonyms:
interface I {
void foo();
}
class Base {
public void foo() { }
}
class Der extends Base implements I {
}
Here Base::foo() will implement I::foo() even if neither Base nor I names or knows about one another. This never happens in C++.
Although my feeling is that the compiler should be able to resolve ambiguities and virtualization here,
Your feeling is based on an incorrect notion of C++ inheritance model; the compiler cannot know your intent. You gave the compiler two different declarations, just because they are homonyms does not mean you intended to have synonyms.
By inheriting from a common interface (with virtual inheritance as you should with interfaces), you are telling the compiler that there is only one feature drive. All uses of drive are synonyms now.

C++ Implement subclasses that extends subInterfaces without overriding already overriden methods

I created Interfaces (abstract classes) that expends other Interfaces in C++ and I tried to implement them but errors occur when I compile.
Here are the errors:
main.cpp: In function 'int main()':
main.cpp:36:38: error: cannot allocate an object of abstract type 'Subclass'
Subclass * subObj = new Subclass();
^
Subclass.h:13:7: note: because the following virtual functions are pure within 'Subclass':
class Subclass : SubInterface {
^
SuperInterface.h:13:18: note: virtual void SuperInterface::doSomething()
virtual void doSomething()=0;
Here are my sources:
#include <iostream>
class SuperInterface {
public:
virtual void doSomething() = 0;
protected:
int someValue;
};
class SubInterface : public SuperInterface {
public:
virtual void doSomethingElseThatHasNothingToDoWithTheOtherMethod() = 0;
protected:
int anotherValue;
};
class Superclass : public SuperInterface {
public:
Superclass() {}
virtual ~Superclass() {}
void doSomething() {std::cout << "hello stackoverflow!";}
};
class Subclass : public SubInterface {
public:
Subclass() {}
virtual ~Subclass() {}
void doSomethingElseThatHasNothingToDoWithTheOtherMethod() {std::cout << "goodbye stackoverflow!";}
};
int main(void)
{
Superclass * superObj = new Superclass();
Subclass * subObj = new Subclass();
}
Here's what I want:
I want my implementation to be aware and so have the same behaviour as of already overriden methods (e.g subObj->doSomething() method works without the need to implement it again). Can anyone tell me what I should do to make that happen if it's even possible? Thanks.
No, you can't do what you want through simple inheritance. At no point does Subclass inherit, or provide, an implementation of doSomething(), so you can't call subObj->doSomething() as you desire. You must honour the interface contract of subInterface.
You could inherit Subclass from Superclass and Subinterface, and just implement doSomething() as a kind of proxy, Superclass::doSomething(). You still need an implementation but you don't have to 're-implement' it.
You're getting the error because you're trying to create an object of an abstract class.
Your Subclass is an abstract class because of this line void doSomethingElse()=0;.
If a class has one pure virtual function, it will be an abstract class. You can't create an object of an abstract class, you can only have a reference or a pointer to it.
To get rid of the error, the declaration of doSomethingElse in Subclass should be
void doSomethingElse();
Instead of void doSomethingElse()=0;
Also I don't see why you need two interfaces. You could derive Subclass from the SuperInterface, as it is basically just the same as SubInterface
To be honest, I am not entirely sure what your design wants to express, but there are at least two technical errors here:
1.) You use private inheritance in all cases, so you do not actually deal with "interfaces" at all. Public inheritance is achieved like this:
class SubInterface : public SuperInterface
2.) You use =0 for a function you apparently want to implement.
This will fix the compiler errors, but the design is still questionable. Considering the motivation you gave at the end of your question, I recommend composition rather than (public) inheritance. In C++, to share functionality is best expressed with composition. To put it very brief, encapsulate the commonly used functionality in a separate class and equip the other classes with an object of it.
class CommonFunctionality
{
//...
public:
void doSomething();
void doSomethingElse();
};
class SuperClass
{
//...
private:
CommonFunctionality m_functionality;
};
class SubClass : public SuperClass
{
//...
private:
CommonFunctionality m_functionality;
};
In fact, perhaps you don't even need to create a class for CommonFunctionality. Perhaps simple free-standing functions would do. Programmers with a Java background (and your code looks a bit like it) tend to put too stuff into classes than what is necessary in C++.
Your class 'Subclass' should override 2 pure virtual methods, so:
class Subclass : SubInterface {
public:
Subclass();
virtual ~Subclass();
void doSomethingElse() override;
void doSomething() override;
};
by not doing so or stating
void doSomethingElse()=0;
class Subclass becomes abstract too, which cannot be instantiated. You could havea look at :http://www.parashift.com/c++-faq-lite/pure-virtual-fns.html
Here's what I want: I want my implementation to be aware and so have
the same behaviour as of already overriden methods (e.g
subObj->doSomething() method works without the need to implement it
again). Can anyone tell me what I should do to make that happen if
it's even possible!!?? Thanks.
--> maybe declare the methods virtual not pure virtual
There are 2 problems, which are clearly stated by compiler:
Problem 1
SubInterface::doSomethingElse()() in Subclass is declared as pure virtual, disregarding that you trying to define it in source file (I'm pretty sure, that this is a copy-paste kind of errors).
class Subclass : SubInterface
{
public:
Subclass();
virtual ~Subclass();
void doSomethingElse() = 0; // still pure?
};
Solution is obvious:
class Subclass : SubInterface
{
public:
Subclass();
virtual ~Subclass();
virtual void doSomethingElse() override
{
}
};
(here using C++11 override specifier, so compiler will check correctness of overriding; it is not obligatory)
Problem 2
doSomething() is not even tried to be overriden, neither in SuperInterface, nor in Subclass, so it stays pure virtual. Although doSomething() is overriden in Superclass, Subclass has no idea about existance of Superclass.
Solution: override doSomething() either in SuperInterface, or in Subclass, or in any of children of Subclass (don't have them yet). For example, overriding in Subclass:
class Subclass : SubInterface
{
public:
Subclass();
virtual ~Subclass();
virtual void doSomething() override
{
}
virtual void doSomethingElse() override
{
}
};
Other issues:
You are inheriting without visibility specifier, i.e. privately. Use public inheritance until you really need something else:
class Derved : public Base {};
Your source files have .c extension, but containing C++ code. This can confuse some compilers if you do not state programming language explicitly via command line arguments. By convention, most programmers use .cpp extension, and most compilers treat such files as C++ source files.

What is the purpose of the "final" keyword in C++11 for functions?

What is the purpose of the final keyword in C++11 for functions? I understand it prevents function overriding by derived classes, but if this is the case, then isn't it enough to declare as non-virtual your final functions? Is there another thing I'm missing here?
What you are missing, as idljarn already mentioned in a comment is that if you are overriding a function from a base class, then you cannot possibly mark it as non-virtual:
struct base {
virtual void f();
};
struct derived : base {
void f() final; // virtual as it overrides base::f
};
struct mostderived : derived {
//void f(); // error: cannot override!
};
It is to prevent a class from being inherited. From Wikipedia:
C++11 also adds the ability to prevent inheriting from classes or simply preventing overriding methods in derived classes. This is done with the special identifier final. For example:
struct Base1 final { };
struct Derived1 : Base1 { }; // ill-formed because the class Base1
// has been marked final
It is also used to mark a virtual function so as to prevent it from being overridden in the derived classes:
struct Base2 {
virtual void f() final;
};
struct Derived2 : Base2 {
void f(); // ill-formed because the virtual function Base2::f has
// been marked final
};
Wikipedia further makes an interesting point:
Note that neither override nor final are language keywords. They are technically identifiers; they only gain special meaning when used in those specific contexts. In any other location, they can be valid identifiers.
That means, the following is allowed:
int const final = 0; // ok
int const override = 1; // ok
"final" also allows a compiler optimization to bypass the indirect call:
class IAbstract
{
public:
virtual void DoSomething() = 0;
};
class CDerived : public IAbstract
{
void DoSomething() final { m_x = 1 ; }
void Blah( void ) { DoSomething(); }
};
with "final", the compiler can call CDerived::DoSomething() directly from within Blah(), or even inline. Without it, it has to generate an indirect call inside of Blah() because Blah() could be called inside a derived class which has overridden DoSomething().
Nothing to add to the semantic aspects of "final".
But I'd like to add to chris green's comment that "final" might become a very important compiler optimization technique in the not so distant future. Not only in the simple case he mentioned, but also for more complex real-world class hierarchies which can be "closed" by "final", thus allowing compilers to generate more efficient dispatching code than with the usual vtable approach.
One key disadvantage of vtables is that for any such virtual object (assuming 64-bits on a typical Intel CPU) the pointer alone eats up 25% (8 of 64 bytes) of a cache line. In the kind of applications I enjoy to write, this hurts very badly. (And from my experience it is the #1 argument against C++ from a purist performance point of view, i.e. by C programmers.)
In applications which require extreme performance, which is not so unusual for C++, this might indeed become awesome, not requiring to workaround this problem manually in C style or weird Template juggling.
This technique is known as Devirtualization. A term worth remembering. :-)
There is a great recent speech by Andrei Alexandrescu which pretty well explains how you can workaround such situations today and how "final" might be part of solving similar cases "automatically" in the future (discussed with listeners):
http://channel9.msdn.com/Events/GoingNative/2013/Writing-Quick-Code-in-Cpp-Quickly
Final cannot be applied to non-virtual functions.
error: only virtual member functions can be marked 'final'
It wouldn't be very meaningful to be able to mark a non-virtual method as 'final'. Given
struct A { void foo(); };
struct B : public A { void foo(); };
A * a = new B;
a -> foo(); // this will call A :: foo anyway, regardless of whether there is a B::foo
a->foo() will always call A::foo.
But, if A::foo was virtual, then B::foo would override it. This might be undesirable, and hence it would make sense to make the virtual function final.
The question is though, why allow final on virtual functions. If you have a deep hierarchy:
struct A { virtual void foo(); };
struct B : public A { virtual void foo(); };
struct C : public B { virtual void foo() final; };
struct D : public C { /* cannot override foo */ };
Then the final puts a 'floor' on how much overriding can be done. Other classes can extend A and B and override their foo, but it a class extends C then it is not allowed.
So it probably doesn't make sense to make the 'top-level' foo final, but it might make sense lower down.
(I think though, there is room to extend the words final and override to non-virtual members. They would have a different meaning though.)
A use-case for the 'final' keyword that I am fond of is as follows:
// This pure abstract interface creates a way
// for unit test suites to stub-out Foo objects
class FooInterface
{
public:
virtual void DoSomething() = 0;
private:
virtual void DoSomethingImpl() = 0;
};
// Implement Non-Virtual Interface Pattern in FooBase using final
// (Alternatively implement the Template Pattern in FooBase using final)
class FooBase : public FooInterface
{
public:
virtual void DoSomething() final { DoFirst(); DoSomethingImpl(); DoLast(); }
private:
virtual void DoSomethingImpl() { /* left for derived classes to customize */ }
void DoFirst(); // no derived customization allowed here
void DoLast(); // no derived customization allowed here either
};
// Feel secure knowing that unit test suites can stub you out at the FooInterface level
// if necessary
// Feel doubly secure knowing that your children cannot violate your Template Pattern
// When DoSomething is called from a FooBase * you know without a doubt that
// DoFirst will execute before DoSomethingImpl, and DoLast will execute after.
class FooDerived : public FooBase
{
private:
virtual void DoSomethingImpl() {/* customize DoSomething at this location */}
};
final adds an explicit intent to not have your function overridden, and will cause a compiler error should this be violated:
struct A {
virtual int foo(); // #1
};
struct B : A {
int foo();
};
As the code stands, it compiles, and B::foo overrides A::foo. B::foo is also virtual, by the way. However, if we change #1 to virtual int foo() final, then this is a compiler error, and we are not allowed to override A::foo any further in derived classes.
Note that this does not allow us to "reopen" a new hierarchy, i.e. there's no way to make B::foo a new, unrelated function that can be independently at the head of a new virtual hierarchy. Once a function is final, it can never be declared again in any derived class.
The final keyword allows you to declare a virtual method, override it N times, and then mandate that 'this can no longer be overridden'. It would be useful in restricting use of your derived class, so that you can say "I know my super class lets you override this, but if you want to derive from me, you can't!".
struct Foo
{
virtual void DoStuff();
}
struct Bar : public Foo
{
void DoStuff() final;
}
struct Babar : public Bar
{
void DoStuff(); // error!
}
As other posters pointed out, it cannot be applied to non-virtual functions.
One purpose of the final keyword is to prevent accidental overriding of a method. In my example, DoStuff() may have been a helper function that the derived class simply needs to rename to get correct behavior. Without final, the error would not be discovered until testing.
Final keyword in C++ when added to a function, prevents it from being overridden by derived classes.
Also when added to a class prevents inheritance of any type.
Consider the following example which shows use of final specifier. This program fails in compilation.
#include <iostream>
using namespace std;
class Base
{
public:
virtual void myfun() final
{
cout << "myfun() in Base";
}
};
class Derived : public Base
{
void myfun()
{
cout << "myfun() in Derived\n";
}
};
int main()
{
Derived d;
Base &b = d;
b.myfun();
return 0;
}
Also:
#include <iostream>
class Base final
{
};
class Derived : public Base
{
};
int main()
{
Derived d;
return 0;
}
Final keyword have the following purposes in C++
If you make a virtual method in base class as final, it cannot be overridden in the derived class. It will show a compilation error:
class Base {
public:
virtual void display() final {
cout << "from base" << endl;
}
};
class Child : public Base {
public:
void display() {
cout << "from child" << endl;
}
};
int main() {
Base *b = new Child();
b->display();
cin.get();
return 0;
}
If we make a class as final, it cannot be inherited by its child classes:
class Base final {
public:
void displayBase() {
cout << "from base" << endl;
}
};
class Child :public Base {
public:
void displayChild() {
cout << "from child" << endl;
}
};
Note: the main difference with final keyword in Java is ,
a) final is not actually a keyword in C++.
you can have a variable named as final in C++
b) In Java, final keyword is always added before the class keyword.
Supplement to Mario Knezović 's answer:
class IA
{
public:
virtual int getNum() const = 0;
};
class BaseA : public IA
{
public:
inline virtual int getNum() const final {return ...};
};
class ImplA : public BaseA {...};
IA* pa = ...;
...
ImplA* impla = static_cast<ImplA*>(pa);
//the following line should cause compiler to use the inlined function BaseA::getNum(),
//instead of dynamic binding (via vtable or something).
//any class/subclass of BaseA will benefit from it
int n = impla->getNum();
The above code shows the theory, but not actually tested on real compilers. Much appreciated if anyone paste a disassembled output.

Multiple inheritance and pure virtual functions

The following code:
struct interface_base
{
virtual void foo() = 0;
};
struct interface : public interface_base
{
virtual void bar() = 0;
};
struct implementation_base : public interface_base
{
void foo();
};
struct implementation : public implementation_base, public interface
{
void bar();
};
int main()
{
implementation x;
}
fails to compile with the following errors:
test.cpp: In function 'int main()':
test.cpp:23:20: error: cannot declare variable 'x' to be of abstract type 'implementation'
test.cpp:16:8: note: because the following virtual functions are pure within 'implementation':
test.cpp:3:18: note: virtual void interface_base::foo()
I have played around with it and figured out that making the 'interface -> interface_base' and 'implementation_base -> interface_base' inheritances virtual, fixes the problem, but I don't understand why. Can someone please explain what is going on?
p.s. I omitted the virtual destructors on purpose to make the code shorter. Please don't tell me to put them in, I already know :)
You have two interface_base base classes in your inheritance tree. This means you must provide two implementations of foo(). And calling either of them will be really awkward, requiring multiple casts to disambiguate. This usually is not what you want.
To resolve this, use virtual inheritance:
struct interface_base
{
virtual void foo() = 0;
};
struct interface : virtual public interface_base
{
virtual void bar() = 0;
};
struct implementation_base : virtual public interface_base
{
void foo();
};
struct implementation : public implementation_base, virtual public interface
{
void bar();
};
int main()
{
implementation x;
}
With virtual inheritance, only one instance of the base class in question is created in the inheritance heirarchy for all virtual mentions. Thus, there's only one foo(), which can be satisfied by implementation_base::foo().
For more information, see this prior question - the answers provide some nice diagrams to make this all more clear.
The usual C++ idiom is:
public virtual inheritance for interface classes
private non-virtual inheritance for implementation classes
In this case we would have:
struct interface_base
{
virtual void foo() = 0;
};
struct interface : virtual public interface_base
{
virtual void bar() = 0;
};
struct implementation_base : virtual public interface_base
{
void foo();
};
struct implementation : private implementation_base,
virtual public interface
{
void bar();
};
In implementation, the unique interface_base virtual base is :
publicly inherited via interface: implementation --public--> interface --public--> interface_base
privately inherited via implementation_base: implementation --private--> implementation_base --public--> interface_base
When client code does one of these derived to base conversions:
derived to base pointer conversions,
reference binding of base type with an initializer of static type derived,
access to inherited base class members via a lvalue of derived static type,
what matters is only that there is a least one accessible inheritance path from the derived class to the given base class subobject; other inaccessible paths are simply ignored. Because inheritance of the base class is only virtual here, there is only one base class subject so these conversions are never ambiguous.
Here, the conversion from implementation to interface_base, can always be done by client code via interface; the other inaccessible path does not matter at all. The unique interface_base virtual base is publicly inherited from implementation.
In many cases, the implementation classes (implementation, implementation_base) will be kept hidden from client code: only pointers or references to the interface classes (interface, interface_base) will be exposed.
For the case of 'solving' the diamond inheritance problem, the solutions offered by bdonlan are valid. Having said that, you can avoid the diamond-problem with design. Why must every instance of a given class be seen as both classes? Are you ever going to pass this same object to a class that says something like:
void ConsumeFood(Food *food);
void ConsumeDrink(Drink *drink);
class NutritionalConsumable {
float calories() = 0;
float GetNutritionalValue(NUTRITION_ID nutrition) = 0;
};
class Drink : public NutritionalConsumable {
void Sip() = 0;
};
class Food : public NutritionalConsumable {
void Chew() = 0;
};
class Icecream : public Drink, virtual public Food {};
void ConsumeNutrition(NutritionalConsumable *consumable) {
ConsumeFood(dynamic_cast<Food*>(food));
ConsumeDrink(dynamic_cast<Drink*>(drink));
}
// Or moreso
void ConsumeIcecream(Icecream *icecream) {
ConsumeDrink(icecream);
ConsumeFood(icecream);
}
Surely it would be better in this case for Icecream to just implement NutritionalConsumable and provide a GetAsDrink() and GetAsFood() method that will return a proxy, purely for the sake of appearing as either food or drink. Otherwise that suggests that there is a method or object that accepts a Food but somehow wants to later see it as a Drink, which can only be achieved with a dynamic_cast, and needn't be the case with a more appropriate design.

Overwriting pure virtual functions by 'using' a separately inherited method

Just a small annoyance really as I can work around the problem by wrapping the derived function instead of using the 'using' keyword but why doesn't the following work (the compiler tells me that 'get_elem' is still pure virtual in 'Bar' class).
class Elem {};
class DerivedElem : public Elem {};
class Foo {
public:
virtual Elem& get_elem() = 0;
};
class Goo {
protected:
DerivedElem elem;
public:
DerivedElem& get_elem() { return elem; }
};
class Bar : public Foo, public Goo {
public:
using Goo::get_elem;
};
int main(void) {
Bar bar;
}
Cheers,
Tom
If Goo is a "mixin" designed to implement the interface Foo in a particular way (there could be other mixins with other implementations), then Goo can derive from Foo (instead of Bar doing so).
If Goo isn't designed to implement the interface Foo, then it would be a terrible mistake to treat Bar as though it had implemented that pure virtual function, when it fact it just happens to have a function of the same signature. If you want implicit interfaces and "duck" typing in C++ you can do it, but you have to do it with templates. Rightly or wrongly, pure virtual functions are for explicitly declared interfaces, and Goo's get_elem function is not explicitly declared to implement Foo::get_elem. So it doesn't.
I guess that doesn't explain why in principle the language couldn't define using Goo::get_elem for Foo;, or some such declaration in Bar, to avoid the need for Bar to contain a lot of boilerplate wrapping the call.
You can maybe do something with templates to allow Goo to support this to some extent, without really knowing about Foo:
template <typename T>
class Goo : public T {
protected:
DerivedElem elem;
public:
DerivedElem& get_elem() { return elem; }
};
class Bar : public Goo<Foo> {};
class Baz : public Goo<Fuu> {};
Where Fuu is some other interface that has a get_elem function. Obviously it's then the responsibility of the author of Bar to ensure that Goo really does implement the contract of Foo, and the same for Baz checking the contract of Fuu.
By the way, this form of covariance is a bit dodgy. Looking at Foo, someone might expect the expression bar.get_elem() = Elem() to be valid, and it isn't, so LSP is violated. References are funny like that. ((Foo &)bar).get_elem() = Elem() is valid but in general doesn't work! It only assigns to the Elem sub-object, and for that matter so does ((Foo &)bar).get_elem() = DerivedElem(). Polymorphic assignment is basically a nuisance.
In your example, the Foo and Goo are separate classes. In Bar, the method get_elem from Goo is not at all the same with the one in Foo, even if their signature match.
By having using Goo::get_elem, you simply tell the compiler to resolve unqualified call to get_elem() to the one in Goo.
You've encountered one of the many odd corners of C++. In this case C++ does not consider two virtual functions inherited from different classes to be the same function even though they have the same name and type signature.
There are some good reasons for C++ to act this way. For example, it's frequently the case that those two functions really aren't the same, despite the fact they have the same name and type signature. The semantic meaning of the two functions are different.
Here is an example:
namespace vendor1 {
class Circle {
public:
virtual ::std::size_t size() const { return sizeof(*this); }
};
} // namespace vendor1
namespace vendor2 {
class Shape {
public:
virtual double size() const = 0;
};
class Circle : public Shape {
public:
virtual double size() const { return radius_ * radius_ * M_PI; }
};
} // namespace vendor2
And then you try this:
namespace my_namespace {
class Circle : public ::vendor1::Circle, public ::vendor2::Circle {
// Oops, there is no good definition for size
};
So you have to resort to this:
namespace my_namespace {
class Vendor1Circle : public ::vendor1::Circle {
public:
virtual ::std::size_t data_structure_size() const { return size(); }
};
class Vendor2Circle : public ::vendor2::Circle {
public:
virtual double area() const { return size(); }
};
class Circle : public Vendor1Circle, public Vendor2Circle {
// Now size is still ambiguous and should stay that way
// And in my opinion the compiler should issue a warning if you try
// to redefine it
};
So, C++ has good reason to treat virtual functions with the same type signature (the return type is not part of the type signature) and name from two different bases as different functions.
As far as using goes... All a using directive says is "Add the names from this other namespace to this namespace as if there were declared here.". This is a null concept as far as virtual functions are concerned. It merely suggests that any ambiguity when using a name should be resolved a different way. It only declares a name, it doesn't define the name. In order for a virtual function to be overridden a new definition is required.
OTOH, if you put in a simple thunk redefinition inline like this:
class Bar : public Foo, public Goo {
public:
virtual DerivedElem& get_elem() { return Goo::get_elem(); }
};
a good compiler should see that and know to not even bother to create the function, and instead just fiddle the virtual table entries to do the right thing. It may need to actually emit code for it and have the symbol available in case its address is taken, but it should still be able to simply fiddle the virtual table into having the function completely disappear when called through a Foo *.