-1

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);
}
Maloooo
  • 13
  • 1
  • 4
  • 4
    If you are just starting with C++, then the best course of action is to try ignoring most you know about C#, and not trying to translate C# code to C++. Learn C++ first (without comparing and relating it to C#), and only after you have sufficient experience and solid footing in C++ you might try translating a C# program to C++. Despite similiarites in the syntax of language constructs, both environments are substantially different so that it really makes not much sense for a beginner in C++ to attempt translating C# code into C++ code. –  Mar 31 '19 at 18:12
  • There are a some significant differences between C# and C++ especially in this part. There are plenty of tutorials, some keywords: inheritance, virtual and pure virtual functions. If you query Google with those keywords you will certainly find something that explains why your code is not working properly. Hint: polymorphism forces you to use pointers in almost every case. – Timo Mar 31 '19 at 18:15
  • https://stackoverflow.com/questions/318064/how-do-you-declare-an-interface-in-c?rq=1 – battlmonstr Mar 31 '19 at 18:15

1 Answers1

3

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;
}
Cruz Jean
  • 2,761
  • 12
  • 16
  • Thanks Cruz Jean for the advice. I'm actually learning the fundamentals and in the meantime trying to write some code that is familiar to me in order to exercise. I've updated the answer with my C++ implementation, could you give some advice anyway even if you do not agree with what I'm doing? – Maloooo Mar 31 '19 at 18:55
  • @Maloooo Well in the C++ code you're creating an instance of an interface (in main) - you can't do that. That's like writing `IGameView view = new IGameView()` in C# - not legal. You're probably meaning to create an instance of `GameView` there instead. – Cruz Jean Mar 31 '19 at 20:09
  • @Maloooo Actually, I'll just edit my answer with code and comments explaining why to do what where. one sec. – Cruz Jean Mar 31 '19 at 20:12
  • wow thank you so much! This was really helpful! I'll try now to put it back into separate headers and cpp files and see how it goes :) – Maloooo Mar 31 '19 at 21:16
  • @Maloooo The only thing to watch out for is dangling pointers/references. But I'm sure if you're reading a book/tutorial on C++ they'll tell you all about that. Happy C++ing! – Cruz Jean Mar 31 '19 at 21:24
  • I was wondering, is it like a best practice or convention to declare an interface as struct like you did? @Cruz Jean – Maloooo Mar 31 '19 at 21:26
  • @Maloooo By default interfaces are meant to only contain public functions (like C# enforces). By making it a struct instead of a class it hints to users that it's all public stuff, plus you avoid having to put the `public:` in there. I just think it looks better. Unlike in C#, in C++ class/struct only differ in default public vs. private. – Cruz Jean Mar 31 '19 at 21:29
  • I see, yeah make sense! I'll add that to my best practices then :) – Maloooo Mar 31 '19 at 21:33