Implementing Interfaces in C ++

I usually program in C #, but try to do a bit of C ++ and try to implement interfaces in C ++ a bit.

In C #, I would do something like this:

class Base<T> { public void DoSomething(T value) { // Do something here } } interface IDoubleDoSomething { void DoSomething(double value); } class Foo : Base<double>, IDoubleDoSomething { } 

In C ++, I implemented it as follows:

 template <class T> class Base { public: virtual void DoSomething(T value) { // Do something here } }; class IDoubleDoSomething { public: virtual void DoSomething(double value) = 0; }; class Foo : public Base<double>, public IDoubleDoSomething { }; 

The problem is that I cannot create an instance of Foo because it is abstract (does not implement DoSomething). I understand that I can implement DoSomething and just call the method based on it, but I was hoping this was the best way to do this. I have other classes that inherit a database with different data types, and I have other classes that inherit from IDoubleDoSomething that don't use Base.

Any help was appreciated.

+8
c ++ c # interface multiple-inheritance porting
source share
6 answers

As others noted, the two functions in the base classes are not related (despite the fact that they have the same names and types of arguments), since they do not have a common base class. If you want them to be related to each other, you need to give them a common base class.

In addition, in the general case, if you want multiple inheritance to work correctly, you need to declare your non-private base classes as virtual . Otherwise, if you ever have common base classes (as is often required for this code style), bad things will happen.

So you can do your example as follows:

 template <class T> class IDoSomething { public: virtual void DoSomething(T value) = 0; }; template <class T> class Base : public virtual IDoSomething<T> { public: virtual void DoSomething(T value) { // Do something here } }; class IDoubleDoSomething : public virtual IDoSomething<double> { }; class Foo : public virtual Base<double>, public virtual IDoubleDoSomething { }; 
+1
source share

Consider the following C ++ code

 class Foo { public: void DoSomething1(){} }; template<typename t> void MethodExpectsDosomething1( tf ) { f.DoSomething1(); } template<typename t> void MethodExpectsDosomething2( tf ) { f.DoSomething2(); } int main() { Foo f; MethodExpectsDosomething1<Foo>( f ); MethodExpectsDosomething2<Foo>( f ); return 0; } 

In C ++, you can use Foo without implementing IDoSomething1 and IDoSomething2 . The second MethodExpectsDosomething2 method simply does not compile, since Foo does not have a DoSomething2 method.

In C #, such a construction is not possible and forces you to have the IDoSomething1 and IDoSomething2 and specify this as a type constraint .

Perhaps you need to look at your code and see if such interfaces are needed at all?

+2
source share

In C ++, pure virtual functions must always be redefined in a derived class; they cannot inherit overrides from other base classes. If you need dynamic polymorphism, I don't think there is a reasonable alternative to writing a function in Foo that calls the Base function. Note that the Base function does not have to be virtual.

Depending on how you use these classes (in particular, whether the actual type of each instance of the interface is known at compile time), you can use static polymorphism to embed your specific implementation class in its user as a template parameter; eg:

 // No explicit interface specification with static polymorphism class Foo : public Base<double> { // Inherits DoSomething(double) }; // Template can used with any class that impelements a // "DoSomething" function that can accept a double. template <class DoubleDoSomething> void DoSomethingWithDouble(DoubleDoSomething & interface, double value) { interface.DoSomething(value); } // This particular specialisation uses a "Foo" object. Foo foo; DoSomethingWithDouble(foo, 42); 
+2
source share

The fact is that Base::DoSomething and IWhatever::DoSomething are two unrelated functions (even if there are no pure virtual functions in it, you cannot call DoSomething in the Foo object anyway). Base must be inherited from IWhatever for this to work.

So ask yourself if you really need it. General programming using templates (and concepts that are similar to interfaces - see Boost.ConceptCheck ) is generally a better solution in C ++ than a run-time subtype polytype.

+2
source share

You can pass the second template parameter to Base, the interface that it should implement:

 template <typename T, class Interface> class Base : public Interface { ... }; class Foo : public Base<double, IDoubleDoSomething> { ... }; 

For additional bonus points, you can templatise IDoubleDoSomething (for example, IDoSomething<double> ) or use the feature class to match the type T with the corresponding interface.

+2
source share

If everything else is in order, this should work.

 class Foo : public Base<double> { }; 

In your source code, Foo will have 2 methods void DoSomething (double value) (1 is abstract). This will be the base part and part of IDoubleDoSomething. Foo :: Base and Foo :: IDoubleDoSomething. You can try this by temporarily providing and executing IDoubleDoSomething.DoSomething ().

But since Foo is already "base", you have what you need without IDoubleDoSomething.

-one
source share

All Articles