How to Declare an Interface in C++

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.

how to implement Interfaces in C++? [duplicate]

C++ has no built-in concepts of interfaces. You can implement it using abstract classes which contains only pure virtual functions. Since it allows multiple inheritance, you can inherit this class to create another class which will then contain this interface (I mean, object interface :) ) in it.

An example would be something like this -

class Interface
{
public:
Interface(){}
virtual ~Interface(){}
virtual void method1() = 0; // "= 0" part makes this method pure virtual, and
// also makes this class abstract.
virtual void method2() = 0;
};

class Concrete : public Interface
{
private:
int myMember;

public:
Concrete(){}
~Concrete(){}
void method1();
void method2();
};

// Provide implementation for the first method
void Concrete::method1()
{
// Your implementation
}

// Provide implementation for the second method
void Concrete::method2()
{
// Your implementation
}

int main(void)
{
Interface *f = new Concrete();

f->method1();
f->method2();

delete f;

return 0;
}

Interface/Implementation in ANSI C

It sounds like you are already doing the right thing: good C code also organizes interfaces in .h-files and implementations in .c-files.

Example a.h file:

void f(int a);

Example a.c file:

#include "a.h"
static void helper(void) {...}
void f(int a) {... use helper()...}

Example main.c file:

#include "a.h"
int main(void) { f(123); return 0; }

You get modularity because helper-functions are not declared in headers so other modules dont know about them (you can declare them at the top of the .c file if you want). Having this modularity reduces the number of recompiles needed and reduces how much has to be recompiled. (The linking has to be done every time though). Note that if you are not declaring helper-functions in the header then you are already pretty safe, however having the static in front of them also hides them from other modules during linking so there is no conflict if multiple modules use the same helper-function-names.

If you are working with only primitive types then that is all you need to know and you can stop reading here. However if your module needs to work with a struct then it gets just a little more complicated.

Problematic example header b.h:

typedef struct Obj {
int data;
}*Obj;
Obj make(void);
void work(Obj o);

Your module wants to pass objects in and out. The problem here is, that internals are leaked to other modules that depend on this header. If the representation is changed to float data then all using modules have to recompile. One way to fix this is to only use void*. That is how many programs do it. However that is cumbersome because every function getting the void* as argument has to cast it to Obj. Another way is to do this:

Header c.h:

typedef struct Obj*Obj;
Obj make(void);
void work(Obj);

Implementation c.c:

#include "c.h"
typedef struct Obj {
int data;
}*Obj;

The reason why this works is, that Obj is a pointer (as opposed to a struct by value/copy). Other modules that depend on this module only need to know that a pointer is being passed in and out, not what it points to.

Interfaces in C

Your two structs aren't compatible since they are different types. You have already found the chapter "compatible types" that defines what makes two structs compatible. The UB comes later when you access these structs with a pointer to the wrong type, strict aliasing violation as per 6.5/7.

The obvious way to solve this would have been this:

struct tcp_application_impl_t{
struct application_t app;
int client_fd;
int socket_fd;
}

Now the types may alias, since tcp_application_impl_t is an aggregate containing a application_t among its members.

An alternative to make this well-defined, is to use a sneaky special rule of "union common initial sequence", found hidden in C17 6.5.2.3/6:

One special guarantee is made in order to simplify the use of unions: if a union contains
several structures that share a common initial sequence (see below), and if the union
object currently contains one of these structures, it is permitted to inspect the common
initial part of any of them anywhere that a declaration of the completed type of the union
is visible. Two structures share a common initial sequence if corresponding members
have compatible types (and, for bit-fields, the same widths) for a sequence of one or more initial members.

This would allow you to use your original types as you declared them. But somewhere in the same translation unit, you will have to add a dummy union typedef to utilize the above rule:

typedef union
{
struct application_t app;
struct tcp_application_impl_t impl;
} initial_sequence_t;

You don't need to actually use any instance of this union, it just needs to sit there visible. This tells the compiler that these two types are allowed to alias, as far as their common initial sequence goes. In your case, it means the function pointers but not the trailing variables in tcp_application_impl_t.

Edit:

Disclaimer. The common initial sequence trick is apparently a bit controversial, with compilers doing other things with it than the committee intended. And possibly works differently in C and C++. See union 'punning' structs w/ "common initial sequence": Why does C (99+), but not C++, stipulate a 'visible declaration of the union type'?

Best way to declare an interface in C++11

What about:

class Testable
{
public:
virtual ~Testable() { }
virtual void test() = 0;
}

In C++ this makes no implications about copyability of child classes. All this says is that the child must implement test (which is exactly what you want for an interface). You can't instantiate this class so you don't have to worry about any implicit constructors as they can't ever be called directly as the parent interface type.

If you wish to enforce that child classes implement a destructor you can make that pure as well (but you still have to implement it in the interface).

Also note that if you don't need polymorphic destruction you can choose to make your destructor protected non-virtual instead.

How is it possible to initialize an interface?

It was an interop ability of COM

Microsoft.Office.Excel API including the Application class, are written in C++

Due to architectural in C++ are more freedom, initialize an interface is needed in some case

.

.NET uses CoClass attribute on a COM object to workaround with initiate an interface

C# wont allow to initiate an interface, but with a CoClass attribute, the interface initialization can be routed to the class CoClass

(example code worth thousand words) So lets reproduce this workaround:

[CoClass(typeof(SugarGlider))] 
[ComImport] // pretend as a COM class
[Guid("000208D5-0000-0000-C000-000000000046")] // put it randomly just to fool the ComImport
public interface ISquirrel
{
string Foo();
}

[ClassInterface(ClassInterfaceType.None)]
public class SugarGlider : ISquirrel
{
public string Foo(){ return "Bar"; }
}

You can now initiate the interface by new ISquirrel()

Full example and runs online: https://rextester.com/ORAZQ51751

Declare interface and Implement the interface using multi-inheritance in C++

I suggest two alternatives.

1. Split the interface

Define two interfaces, Interface1 with interf1 method, and Interface2 with interf2 method. Define two implementations Implement1 and Implement2 which inherit from their corresponding (single) interface. Combine those by inheriting from both Implement1 and Implement2.

The problem is that you then can't have a common interface to use as a polymorphic interface type.

2. Use virtual inheritance for the interface

Live demo

Keep your original Interface definition. The implementations both should virtually derive from the interface: class Implement1 : virtual public Interface { ... };. Then, when combining those implementations, don't derive from the interface again but just from your two implementations. Their super-class Interface is going to be merged to a single one (that's what virtual inheritance is for, basically, it's also called Diamond Inheritance).

In C++11 or above, Is there a way to implement a single-method pure virtual C++ interface by lambda?

You can create a wrapper, e.g.:

class SimpleTask {
public:
virtual void run() = 0;
};

// This class wraps a lambda (or any callable) and implement the run()
// method by simply calling the callable.
template <class T>
class LambdaSimpleTask: public SimpleTask {
T t;

public:
LambdaSimpleTask(T t) : t(std::move(t)) { }

virtual void run() {
t();
}
};


template <class T>
auto makeSimpleTask(T &&t) {
// I am returning a dynamically allocated object following your example,
// but I would rather return a statically allocated one.
return new LambdaSimpleTask<std::decay_t<T>>{std::forward<T>(t)};
}

And then to create the task:

auto task = makeSimpleTask([]() { });
Thread myThread(L"MyTestingThread", task);

Note that you still need to have a wrapper and a makeXXX function for each one of your interface. With C++17 and above, you can get rid of the makeXXX function by using class template argument deduction. Getting rid of the wrapper is not possible but you might be able to reduce the boilerplate code by encapsulating some stuff in macros.


Here is an example macro (not perfect) that could be used to reduce the boilerplate code:

#define WRAPPER_FOR(C, M, ...)                       \
template <class T> \
class Lambda##C: public C { \
T t; \
public: \
Lambda##C(T t) : t(std::move(t)) { } \
virtual M { return t(__VA_ARGS__); } \
}; \
template <class T> auto make##C(T &&t) { \
return Lambda##C<std::decay_t<T>>{std::forward<T>(t)}; }

And then:

class SimpleTask {
public:
virtual void run() = 0;
};

class ComplexTask {
public:
virtual int run(int, double) = 0;
};

WRAPPER_FOR(SimpleTask, void run());
WRAPPER_FOR(ComplexTask, int run(int a, double b), a, b);

c#: define method in interface

The method FullPrint receives an instance of some type that implements ITest.

An interface, for this example the one named ITest, is essentially a contract definition. It is a promise that any types that implement that interface will contain the defined methods and properties of that interface. This is why interfaces do not have an implementation, it represents a promise/contract.

In your example again, you make a promise/contract that any type that implements ITest will contain method:

void Print(string message);

Your type (not shown) CTest implements that interface. You then create a reference of type ITest to the instance of CTest.



Related Topics



Leave a reply



Submit