Search code examples
c#c++interfacemvp

How do I use interfaces in constructors and methods in C++ properly?


I'm starting to learn C++ and coming from a C# background I'm having a lot of problems.

What I want to do is trying to replicate exactly the same thing that I'm doing in the following C# snippet, with C++. This is just a simple implementation of the MVP pattern, which I use quite a lot.

I tried in many different ways to make this work with proper and modern C++ but it's constantly giving me compilation errors which I do not understand properly. Most of them are due to the fact that I'm not able to find a proper way to pass an Interface as a constructor parameter and also to store an Interface as a field of a class. Could someone translate this C# code into a proper C++ code, or at least give me some advice please? Thanks in advance.

NOTE: I'm trying to make headers files with only classes declaration and cpp files with actual implementation.

// This is my C# implementation that I want to convert in C++

public class Program
{
    public static void Main()
    {
        IGameView view = new GameView();
        Game game = new Game(view);
        view.SetPresenter(game);
    }
}

public interface IGameView
{
    void SetPresenter(Game game);
}

public class GameView : IGameView
{
    public void SetPresenter(Game game)
    {
        _game = game;
    }

    Game _game;
}

public class Game
{
    public Game(IGameView view)
    {
        _view = view;
    }

    IGameView _view;
}

This is the C++ code that I'm trying to make compile. I've put everything here without .h and .cpp for clarity and brevity, but as I said I'm actually separating classes from implementation.

class Game
{
public:
    (IGameView& view) : _view(view)
    { }

    Game operator=(const Game &);

private:
    IGameView& _view;
};

class IGameView
{
public:
    virtual ~IGameView() {}

    virtual void SetPresenter(const Game) = 0;
};

class GameView : public IGameView
{
public:

    GameView();

    void SetPresenter(const Game game) override
    {
        _game = game;
    }

private:
    Game& _game;
};

int main()
{
    IGameView view;
    Game game(view);
    view.SetPresenter(game);
}

Solution

  • elgonzo is right. You shouldn't start learning a language by doing translations, esp. going between something like C# and C++. The only similarity between them is naming conventions for keywords.

    In this case the important difference (aside from how to declare interfaces in C++) is that all types in C++ are held by value, whereas C# classes are held by reference. You can't create an instance of an interface in either language (i.e. you can't do new IGameView() in C#).

    Thus, your Game type can't hold an interface type by value. It needs to be a pointer or reference instead. This is all very different from C#, and I suggest you do as the other commenters have said and learn C++ fundamentals first and come back to this later.

    Edit:

    Here's a working form of the C++ code you posted. It has comments explaining why/when to do what it does.

    // C++ requires declaring types before you use them.
    // if we want to use Game before defining it we must at least declare that it exists.
    class Game;
    
    // this is an interface because it contains abstract (pure virtual) functions.
    // you cannot create an instance of an abstract type - but you can make a reference or pointer to one.
    struct IGameView
    {
        // we might want polymorphic deletion - so to be safe we'll make a virtual dtor.
        virtual ~IGameView() {};
    
        // Game is probably expensive to copy - pass it by reference.
        // = 0 makes this an abstract method, which makes this an abstract type.
        virtual void SetPresenter(Game &game) = 0;
    };
    
    // --------------------------------------------
    
    class Game
    {
    public:
        // take a reference to the (interface) object to use (we can't pass an abstract type by value)
        Game(IGameView &view) : _view(view) { }
    
    private:
        // hold a reference to the IGameView (interface) object.
        // if you ever wanted this to refer to something else this would need to be pointer instead.
        // references are kind of like pointers that cannot be repointed to something else.
        IGameView &_view;
    };
    
    class GameView : public IGameView
    {
    public:
        GameView();
    
        virtual void SetPresenter(Game &game) override
        {
            _game = &game;
        }
    
    private:
        // hold a pointer to the Game object.
        // this has to be a pointer because SetPresenter() needs to be able to repoint it (refences can't do that).
        // for safety, initialize this to null.
        Game *_game = nullptr;
    };
    
    // ---------------------------------------------
    
    int main()
    {
        GameView view; // create the game view to use
        Game game(view); // create the game object and use that view
    
        view.SetPresenter(game); // set the view to use the game object
    
        return 0;
    }