0

I've been going through a C++/SFML tutorial (http://www.gamefromscratch.com/page/Game-From-Scratch-CPP-Edition.aspx) and, having reached the end, started altering the code to try out various things and get more comfortable both with C++ and SFML.

For the menu screen, I decided to create an object for buttons. To this end I created Button.cpp and Button.h, then linked to Button.h in the MainMenu.h file. I added Button button_play as a public member of class MainMenu, however when I call a Button function (for example: button_play.ButtonInit("new-game");), I receive the error: error LNK2019: unresolved external symbol "public: void __thiscall Button::ButtonInit(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?ButtonInit@Button@@QAEXV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z) referenced in function "public: enum MainMenu::MenuResult __thiscall MainMenu::Show(class sf::RenderWindow &)" (?Show@MainMenu@@QAE?AW4MenuResult@1@AAVRenderWindow@sf@@@Z)

I've done a lot of searching around this, and most of the answers I've found revolve around not implementing class member functions correctly, however as far as I can tell I am doing it correctly. I am, however, very new to C++, so it's possible that I'm just missing something.

Here's my code:

MainMenu.h

#pragma once
#include "SFML\Window.hpp"
#include "SFML\Graphics.hpp"
#include "GameObjectManager.h"
#include "Button.h"
#include <list>

class MainMenu
{

public:

MainMenu(){};
~MainMenu() {};
enum MenuResult { Nothing, Exit, Play };

const static GameObjectManager& GetGameObjectManager();

struct MenuItem
    {
    public:
        sf::Rect<int> rect;
        MenuResult action;
    };

MenuResult Show(sf::RenderWindow& window);

static GameObjectManager _gameObjectManager;

Button button_play;

private:
MenuResult GetMenuResponse(sf::RenderWindow& window);
MenuResult HandleClick(int x, int y);
std::list<MenuItem> _menuItems;
};

MainMenu.cpp (this is quite long; I've only included the function that calls ButtonInit() and the function that Show() returns - if you need to see more, let me know and I can include the rest of the code for this file)

#include "stdafx.h"
#include "MainMenu.h"
#include "ServiceLocator.h"
#include "Button.h"

MainMenu::MenuResult MainMenu::Show(sf::RenderWindow& window)
{

button_play.ButtonInit("new-game");

return GetMenuResponse(window);
}



MainMenu::MenuResult  MainMenu::GetMenuResponse(sf::RenderWindow& window)
{
sf::Event menuEvent;

while(42 != 43)
{

    while(window.pollEvent(menuEvent))
    {
        if(menuEvent.type == sf::Event::MouseMoved)
        {
            button_play.Update(window);
        }
        if(menuEvent.type == sf::Event::MouseButtonPressed)
        {
            if(ServiceLocator::GetAudio()->IsSongPlaying())
            {
                ServiceLocator::GetAudio()->StopAllSounds();
            }

            return HandleClick(menuEvent.mouseButton.x,menuEvent.mouseButton.y);
        }
        if(menuEvent.type == sf::Event::Closed)
        {
            return Exit;
        }
    }
}
}

Button.h

#pragma once

class Button
{
public:
Button() {};
~Button() {};

void ButtonInit(std::string name);
void Update(sf::RenderWindow & rw);

};

Button.cpp

#include "StdAfx.h"
#include "Button.h"

void Button::ButtonInit(std::string name)
{
}

void Button::Update(sf::RenderWindow & rw)
{
}

stdafx.h (probably don't need to see this, but just in case)

// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once

#include "targetver.h"

#include <stdio.h>
#include <tchar.h>

// TODO: reference additional headers your program requires here
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/Audio.hpp>

#include <map>
#include <iostream>
#include <cassert>
#include <string>

Any help would be appreciated.

Kaboodleschmitt
  • 453
  • 3
  • 13
  • I think it was an issue with the project in MSVS, I used 'Clean Solution' and 'Rebuild Solution', and after that my Button.cpp file was no longer linked to the solution. Re-linking it got rid of the error. – Kaboodleschmitt Mar 24 '15 at 23:20
  • This question is not a duplicate. – aj.toulan Mar 29 '19 at 19:48

1 Answers1

0

I assume, you have both classes in the same project. The linker-message tells you, that the linker does not find a fitting function definition. So my guess would be ... the linker cannot find a fitting overload of the function. "new-game" is a const char* and it is not a std::string.

a) change your method signature to

void ButtonInit(const char* name);

or b) call your method like:

button_play.ButtonInit(std::string("new-game"));
Mr.Yellow
  • 197
  • 1
  • 8
  • It is fine to call it with a string literal and a `std::string` parameter. – Neil Kirk Mar 24 '15 at 16:07
  • Both classes are in the same project (VC++ 2010), yes. I tried both your suggestions and still receive the original error – Kaboodleschmitt Mar 24 '15 at 16:24
  • Well, the error changed in that 'public: void __thiscall Button::ButtonInit(class std::basic_string,class std::allocator >)' became 'public: void __thiscall Button::ButtonInit(char const *)' – Kaboodleschmitt Mar 24 '15 at 16:33