Why can't I use inheritance to implement an interface in C++?
struct B
is implementing a function that happens to be called foo
and takes no arguments. That function has obviously absolutely no relation to A::foo
. So when struct C
derives from both A
and B
, it ends up having inherited:
- the responsibility to provide an implementation for
A::foo
- a method
B::foo
that has the same name and signature asA::foo
, but is not related to it in any way
I think the problem is obvious. You are trying to use A
as the equivalent of a C# interface
, but there is no way to express that concept in C++.
Now the using
directive also does not help here because all it does is bring B::foo
into the scope of C
, meaning that it tells the compiler it should consider B::foo
as a candidate for resolving the name foo
when the latter is encountered inside class C
. Unfortunately, that's also unrelated to the responsibility of implementing pure virtual methods.
Why an inherited interface can't be converted to its base interface in generic context?
You aren't able to make the assignment because the base class, AbstractClass<T>
, is invariant. What you want to be able to make that kind of assignment is a covariant type. Defining Covariance and Contravariance is limited to interfaces, so that means we need another interface.
public interface IAbstractClass<out T> where T : BaseInterface { }
public abstract class AbstractClass<T> : IAbstractClass<T> where T : BaseInterface { }
The out
keyword marks the generic type parameter as covariant. We then implement that interface in AbstractClass<T>
, and our other types can work expected through the interface. These are also the only alterations we need to make, we leave the other type definitions the same:
public interface BaseInterface { }
public interface ChildInterface : BaseInterface { }
public class ConcreteClass : AbstractClass<ChildInterface> { }
We now have a covariant interface that AbstractClass<T>
implements, and you can do the kind of assignment you desire, but you'll have to target the IAbstractClass
interface.
public void Main() {
IAbstractClass<BaseInterface> c = new ConcreteClass();
}
How do you declare an interface in C++?
To expand on the answer by bradtgmurray, you may want to make one exception to the pure virtual method list of your interface by adding a virtual destructor. This allows you to pass pointer ownership to another party without exposing the concrete derived class. The destructor doesn't have to do anything, because the interface doesn't have any concrete members. It might seem contradictory to define a function as both virtual and inline, but trust me - it isn't.
class IDemo
{
public:
virtual ~IDemo() {}
virtual void OverrideMe() = 0;
};
class Parent
{
public:
virtual ~Parent();
};
class Child : public Parent, public IDemo
{
public:
virtual void OverrideMe()
{
//do stuff
}
};
You don't have to include a body for the virtual destructor - it turns out some compilers have trouble optimizing an empty destructor and you're better off using the default.
Why interface cannot inherit pure abstract class
The major difference between interfaces and classes is that interfaces only provide signatures and not implementations. If the interface inheriting a class inherited its implementation, it would provide implementation and no longer be an interface.
Why is Multiple Inheritance not allowed in Java or C#?
The short answer is: because the language designers decided not to.
Basically, it seemed that both the .NET and Java designers did not allow multiple inheritance because they reasoned that adding MI added too much complexity to the languages while providing too little benefit.
For a more fun and in-depth read, there are some articles available on the web with interviews of some of the language designers. For example, for .NET, Chris Brumme (who worked at MS on the CLR) has explained the reasons why they decided not to:
Different languages actually have different expectations for how MI
works. For example, how conflicts are
resolved and whether duplicate bases
are merged or redundant. Before we can
implement MI in the CLR, we have to do
a survey of all the languages, figure
out the common concepts, and decide
how to express them in a
language-neutral manner. We would also
have to decide whether MI belongs in
the CLS and what this would mean for
languages that don't want this concept
(presumably VB.NET, for example). Of
course, that's the business we are in
as a common language runtime, but we
haven't got around to doing it for MI
yet.The number of places where MI is truly appropriate is actually quite
small. In many cases, multiple
interface inheritance can get the job
done instead. In other cases, you may
be able to use encapsulation and
delegation. If we were to add a
slightly different construct, like
mixins, would that actually be more
powerful?Multiple implementation inheritance injects a lot of complexity into the
implementation. This complexity
impacts casting, layout, dispatch,
field access, serialization, identity
comparisons, verifiability,
reflection, generics, and probably
lots of other places.
You can read the full article here.
For Java, you can read this article:
The reasons for omitting multiple
inheritance from the Java language
mostly stem from the "simple, object
oriented, and familiar" goal. As a
simple language, Java's creators
wanted a language that most developers
could grasp without extensive
training. To that end, they worked to
make the language as similar to C++ as
possible (familiar) without carrying
over C++'s unnecessary complexity
(simple).In the designers' opinion, multiple
inheritance causes more problems and
confusion than it solves. So they cut
multiple inheritance from the language
(just as they cut operator
overloading). The designers' extensive
C++ experience taught them that
multiple inheritance just wasn't worth
the headache.
In C#, can a class inherit from another class and an interface?
Yes. Try:
class USBDevice : GenericDevice, IOurDevice
Note: The base class should come before the list of interface names.
Of course, you'll still need to implement all the members that the interfaces define. However, if the base class contains a member that matches an interface member, the base class member can work as the implementation of the interface member and you are not required to manually implement it again.
When should I choose inheritance over an interface when designing C# class libraries?
Generally, the rule goes something like this:
- Inheritance describes an is-a relationship.
- Implementing an interface describes a can-do relationship.
To put this in somewhat more concrete terms, let's look at an example. The System.Drawing.Bitmap
class is-an image (and as such, it inherits from the Image
class), but it also can-do disposing, so it implements the IDisposable
interface. It also can-do serialization, so it implements from the ISerializable
interface.
But more practically, interfaces are often used to simulate multiple inheritance in C#. If your Processor
class needs to inherit from something like System.ComponentModel.Component
, then you have little choice but to implement an IProcessor
interface.
The fact is that both interfaces and abstract base class provide a contract specifying what a particular class can do. It's a common myth that interfaces are necessary to declare this contract, but that's not correct. The biggest advantage to my mind is that abstract base classes allow you provide default functionality for the subclasses. But if there is no default functionality that makes sense, there's nothing keeping you from marking the method itself as abstract
, requiring that derived classes implement it themselves, just like if they were to implement an interface.
For answers to questions like this, I often turn to the .NET Framework Design Guidelines, which have this to say about choosing between classes and interfaces:
In general, classes are the preferred construct for exposing abstractions.
The main drawback of interfaces is that they are much less flexible than classes when it comes to allowing for the evolution of APIs. Once you ship an interface, the set of its members is fixed forever. Any additions to the interface would break existing types implementing the interface.
A class offers much more flexibility. You can add members to classes that you have already shipped. As long as the method is not abstract (i.e., as long as you provide a default implementation of the method), any existing derived classes continue to function unchanged.
[ . . . ]
One of the most common arguments in favor of interfaces is that they allow separating contract from the implementation. However, the argument incorrectly assumes that you cannot separate contracts from implementation using classes. Abstract classes residing in a separate assembly from their concrete implementations are a great way to achieve such separation.
Their general recommendations are as follows:
- Do favor defining classes over interfaces.
- Do use abstract classes instead of interfaces to decouple the contract from implementations. Abstract classes, if defined correctly, allow for the same degree of decoupling between contract and implementation.
- Do define an interface if you need to provide a polymorphic hierarchy of value types.
- Consider defining interfaces to achieve a similar effect to that of multiple inheritance.
Chris Anderson expresses particular agreement with this last tenet, arguing that:
Abstract types do version much better, and allow for future extensibility, but they also burn your one and only base type. Interfaces are appropriate when you are really defining a contract between two objects that is invariant over time. Abstract base types are better for defining a common base for a family of types.
Related Topics
Receiving Only Necessary Data with C++ Socket
Confused by Squaring MACro Sqr in C
Is Substitution Performed on a Variadic Parameter Pack Type If the Pack Is Empty
Inheriting Constructors and Brace-Or-Equal Initializers
Why Does (1 << 31) >> 31 Result in -1
How to Resume Input Stream After Stopped by Eof in C++
Create 2D Array Using Size from Parameters in C++
Difference Between Static in C and Static in C++
Restrict Passed Parameter to a String Literal
Is There a Readable Implementation of the Stl
Workaround for Error C2536: Cannot Specify Explicit Initializer for Arrays in Visual Studio 2013
When Does an Incomplete Type Error Occur in C++
Is Std::Array<T, S> Guaranteed to Be Pod If T Is Pod
Why It Is Different Between -2147483648 and (Int)-2147483648
Combining Two Lists by Key Using Thrust
C++: Class Declaration and Definition Separated Inside Header Causes Duplicate Symbol
Why Vector.Size()-1 Gives Garbage Value
What Are Consequences of Forcing Qobject as a Parent of Qwidget