I'm having an issue with a pretty simple code
I am following the tutorial of chrono::engine http://www.chronoengine.info/mediawiki/index.php/Demo_fourbar
I do not have much experience in C++ programming (I have some experience in Java), therefore I tried to define MyEventReceiver (a class from the tutorial) in a different file (MyEventReceiver.h and MyEventReceiver.cpp) to get my head around classic structure of a C++ code
Here is the version of the code
MyEventReceiver.h
#ifndef RECEIVER_H
#define RECEIVER_H
#include "physics/CHapidll.h"
#include "physics/CHsystem.h"
#include "irrlicht_interface/CHbodySceneNode.h"
#include "irrlicht_interface/CHbodySceneNodeTools.h"
#include "irrlicht_interface/CHdisplayTools.h"
#include "irrlicht_interface/CHirrWizard.h"
#include "core/CHrealtimeStep.h"
#include <irrlicht.h>
// Use the namespace of Chrono
using namespace chrono;
// Use the main namespaces of Irrlicht
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(ChSystem* asystem, IrrlichtDevice* adevice, ChSharedPtr<ChLinkEngine> aengine);
bool OnEvent(const SEvent& event);
void setText_enginespeed(IGUIStaticText* _text_enginespeed);
IGUIStaticText* getText_enginespeed();
private:
IGUIStaticText* text_enginespeed;
ChSystem* msystem;
IrrlichtDevice* mdevice;
ChSharedPtr<ChLinkEngine> mengine;
};
#endif
with the implementation as follows in MyEventReceiver.cpp
#include "MyEventReceiver.h"
// Constructor
MyEventReceiver::MyEventReceiver(ChSystem *asystem, IrrlichtDevice *adevice, ChSharedPtr<ChLinkEngine> aengine)
{
// store pointer to physical system & other stuff
// so we can tweak them by user keyboard
msystem = asystem;
mdevice = adevice;
mengine = aengine;
}
bool MyEventReceiver::OnEvent(const SEvent& event)
{
// check if user moved the sliders with mouse..
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
IGUIEnvironment* env = mdevice->getGUIEnvironment();
switch(event.GUIEvent.EventType)
{
case EGET_SCROLL_BAR_CHANGED:
if (id == 101) // id of 'engine speed' gui
{
s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
double newspeed = 10*(double)pos/100.0;
// set the speed into engine object
ChFunction_Const *spe_funct = dynamic_cast <ChFunction_Const*> (mengine->Get_spe_funct());
spe_funct->Set_yconst(newspeed);
// show speed as formatted text in interface screen
char message[50]; sprintf(message,"Engine speed: %g [rad/s]",newspeed);
text_enginespeed->setText(core::stringw(message).c_str());
}
break;
}
}
return false;
}
void MyEventReceiver::setText_enginespeed(IGUIStaticText* _text_enginespeed)
{
text_enginespeed = _text_enginespeed;
}
IGUIStaticText* MyEventReceiver::getText_enginespeed()
{
return text_enginespeed;
}
and the main file in Main_2.cpp (which I emptied, it gives me the same error with or without the code inside - which is basically only setting up the 3D engine Irrlicht and some mechanics features from the collision model of chrono::engine)
#include "MyEventReceiver.h"
int main()
{
return 0;
}
Basically the code defines an event receiver, so that the user after running the program can interact with the 3D environment built from the chrono::engine and Irrlicht engine through GUI manipulation
I define all the required libraries in the MyEventReceiver.h file and the required namespaces
The problem is that it does not compile (please note that I already tested the engines - with the same #include and using namespaces in just one file and it was working in a different project - ), i think the problem is coming from the structure of the header files
I got those lines of error
1>MyEventReceiver.obj : error LNK2005: "public: virtual bool __thiscall irr::scene::RTSCamera::OnEvent(struct irr::SEvent const &)" (?OnEvent#RTSCamera#scene#irr##UAE_NABUSEvent#3##Z) already defined in Main_2.obj
1>MyEventReceiver.obj : error LNK2005: "public: virtual void __thiscall irr::scene::RTSCamera::OnRegisterSceneNode(void)" (?OnRegisterSceneNode#RTSCamera#scene#irr##UAEXXZ) already defined in Main_2.obj
etc... (it goes on like this)
and the final mistake
1>C:\Users\****\Documents\Visual Studio 2010\Projects\TutorialChronoEngine\Debug\TutorialChronoEngine_2.exe : fatal error LNK1169: one or more multiply defined symbols found
I am using Visual Studio 2010 C++. I defined one global solution, and several projects in this very solution (the program I wrote above is one project among others)
I am sure it must be pretty easy to solve, but can't really find the solution. Let me know if you need further details
Thanks a lot
Best regards
Vincent
Edit : If I put all the codes in one single file as follows
#include "physics/CHapidll.h"
#include "physics/CHsystem.h"
#include "irrlicht_interface/CHbodySceneNode.h"
#include "irrlicht_interface/CHbodySceneNodeTools.h"
#include "irrlicht_interface/CHdisplayTools.h"
#include "irrlicht_interface/CHirrWizard.h"
#include <irrlicht.h>
// Use the namespace of Chrono
using namespace chrono;
// Use the main namespaces of Irrlicht
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;
// Get rid of the command windows that pops up when compiling and running
#ifdef _IRR_WINDOWS_
#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
IGUIStaticText* text_enginespeed = 0;
class MyEventReceiver : public IEventReceiver
{
public:
MyEventReceiver(ChSystem* asystem,
IrrlichtDevice *adevice,
ChSharedPtr<ChLinkEngine> aengine)
{
// store pointer to physical system & other stuff
// so we can tweak them by user keyboard
msystem = asystem;
mdevice = adevice;
mengine = aengine;
}
bool OnEvent(const SEvent& event)
{
// check if user moved the sliders with mouse..
if (event.EventType == EET_GUI_EVENT)
{
s32 id = event.GUIEvent.Caller->getID();
IGUIEnvironment* env = mdevice->getGUIEnvironment();
switch(event.GUIEvent.EventType)
{
case EGET_SCROLL_BAR_CHANGED:
if (id == 101) // id of 'engine speed' gui
{
s32 pos = ((IGUIScrollBar*)event.GUIEvent.Caller)->getPos();
double newspeed = 10*(double)pos/100.0;
// set the speed into engine object
ChFunction_Const *spe_funct = dynamic_cast <ChFunction_Const*> (mengine->Get_spe_funct());
spe_funct->Set_yconst(newspeed);
// show speed as formatted text in interface screen
char message[50]; sprintf(message,"Engine speed: %g [rad/s]",newspeed);
text_enginespeed->setText(core::stringw(message).c_str());
}
break;
}
}
return false;
}
private:
ChSystem* msystem;
IrrlichtDevice* mdevice;
ChSharedPtr<ChLinkEngine> mengine;
};
int main(int argc, char* argv[])
{
return 0;
}
In that way, I avoid defining several times functions from the Irrlicht 3D engine that are not defined as inline. Unfortunately, this way of coding can become really cumbersome if a project becomes big (having to define all classes that rely on the 3D engine in one unique .cpp file), is there a design pattern to follow so that it is possible to avoid multiple defined objects with each class defined in a separate file ?
Thanks a lot
Best
Vincent
The linker is complaining about two of your functions being defined multiple times. As you could probably figure out from the errors, these functions are:
irr::scene::RTSCamera::OnEvent(struct irr::SEvent const &)
irr::scene::RTSCamera::OnRegisterSceneNode(void)
What's most likely happening here is that these two functions are defined in a header file, but:
Their definition does not appear directly in the class definition (so they are not implicitly declared to be inline);
Their out-of-class definition in the header file is not explicitly marked as inline.
As a result, if the header is included multiple times in different translation units (i.e. in different .cpp files), multiple definitions of the same functions will end up being present in the object code of those translation units.
When merging them, the linker will complain that you are breaking the ODR (One Definition Rule).
Related
I am new to C++ but not to programming. I'm developing a plugin and learning the language at the same time. The plugin is for old software but still being used, so I'm using VS2015 and an SDK to match. I'm having a problem that I just don't know enough to solve but I know that it's the result of something that I'm doing wrong or don't understand. Please also consider that I'm using a third party SDK, with only .H/.HPP files and an occasional .CPP, but that's it. Everything else is wrapped in their libraries. Therefore, I don't have the liberty to change any behavior.
My code snippets are parts of their headers (can't change) and the .cpp is my modified sample code that comes along with their SDK and which I'm using as my base. It is also the area of code that causes the link error. Their samples all work, I can compile them and run them no problem. My code also works and is doing what I want. Things only break when I use my modified code. The reason I'm doing this is because I need access to the message passed into the plugin and can't find any other way to get it other than to try and override "PluginMain". The original sample code actually does call into PluginSetup.cpp because it runs other code within it as setup prior to continuing on. I've only posted the part of my code which is my attempt to override the function as I mentioned and I just included the variable declaration that causes the error. If I comment my variable declaration and other code related to it, program compiles and works again. If I move the variable declaration to another .cpp file in my codebase, code compiles no problem. It just don't like being in PluginSetup.cpp but part from maybe the main.cpp file (which I can't do anything with), PluginSetup.cpp is the first that gets called. So this is where I chose to put my override.
Am I using the friend function correctly? As you can see from the codebase, they've made the ctor as well as the friend function private.
This may also go hand in hand with a question I asked before on how to instantiate a class from this implementation using private friend function and ctors?
Hopefully, what I've posted is enough to give someone all that's needed to figure out what the problem might be.
ns1ns2Main.h
namespace ns1
{
namespace ns2
{
class Plugin;
...
}
}
extern "C" __declspec(dllexport) __MainError PluginMain(const char* caller_, const char* selector_, void* message_);
ns1ns2Plugin.h
#include "ns1ns2Main.h"
namespace ns1
{
namespace ns2
{
class Plugin
{
Public:
static Plugin* const instance();
private:
friend __MainError (::PluginMain) (const char*, const char*, void*);
Plugin();
Plugin(const Plugin&);
virtual ~Plugin();
};
}
}
PluginSetup.cpp
#include "ns1ns2Main.h"
#include "ns1ns2Plugin.h"
//-> My Modification Begins
__MainError (::PluginMain) (const char* caller, const char* selector, void* message)
{
ns1::ns2::Plugin plugin;
if (!plugin.instance())
{
plugin = ns1::ns2::Plugin();
}
if (strcmp(caller, kSPInterfaceCaller) == 0)
{
if (strcmp(selector, kSPInterfaceStartupSelector) == 0)
{
bool bStatus = ns1::ns2::pluginSetup(&plugin);
if (bStatus)
{
plugin_ = clpcsx::Plugin::instance();
plugin_->startup();
}
}
else if (strcmp(selector, kSPInterfaceShutdownSelector) == 0)
{
plugin_ = clpcsx::Plugin::instance();
plugin_->shutdown();
}
}
return error;
}
//<- My Modification Ends
namespace ns1
{
namespace ns2
{
void pluginLoaded()
{
// no-op
}
bool pluginSetup(Plugin* const plugin)
{
clpcsx::Plugin::create(plugin);
plugin->setStartupCallback(NS1_NS2_CALLBACK(clpcsx::Plugin, CLPCSX_PLUG_INST, startup));
plugin->setPostStartupCallback(NS1_NS2_CALLBACK(clpcsx::Plugin, CLPCSX_PLUG_INST, postStartup));
plugin->setPreShutdownCallback(NS1_NS2_CALLBACK(clpcsx::Plugin, CLPCSX_PLUG_INST, preShutdown));
plugin->setShutdownCallback(NS1_NS2_CALLBACK(clpcsx::Plugin, CLPCSX_PLUG_INST, shutdown));
return true;
}
void pluginDestroy(Plugin* const plugin)
{
clpcsx::Plugin::destroy();
}
}
}
Link Error
1>PluginSetup.obj : error LNK2019: unresolved external symbol "private: __cdecl ns1::ns2::Plugin::Plugin(void)" (??0Plugin#ns2#ns1##AEAA#XZ) referenced in function PluginMain
You have to tell the linker to include the libraries. Since this is VS you can add to the main .cpp file
#pragma comment(lib, "xxxx.lib")
where 'xxxx.lib' is the name of the library that has those ns functions. You need to make sure they are in the VS linker path too
I'm new to C++ and am trying to learn OpenGL. However, when I try to compile my program, I cannot refer to a namespace that I have already created in my header file. The code is as follows:
engine.hpp:
#ifndef ENGINE_HPP
#define ENGINE_HPP
// ...
namespace render {
void Initialise();
namespace inits {
bool glfw_init = false,
glfw_window_init = false,
gl_init = false;
}
}
#endif
engine.cpp:
#include "engine.hpp"
// ...
namespace render {
void Initialise() {
if (glfwInit() == GLFW_FALSE)
inits::glfw_init = false;
}
}
O
I'm not sure why this isn't compiling. I'm using MinGW (GCC) on Windows 10 (64-bit).
My compiler message is:
error: 'inits' has not been declared
Edit: Thank you everybody for your suggestions. It appears that although this was a compiler fluke (after my first edit, since others could not reproduce the issue and a reinstall fixed the issue), it is a symptom of a larger organisational problem within my code. Since I have only invested ~15 minutes into the program, I would prefer to completely rewrite this after learning more about the language. For now, I have created a class and solved the issue discussed. I'm a beginner, and any book/resource recommendations would be welcome!
You're using nested namespaces, so should be:
render::inits::glfw_init = false;
Your code does not what you think it does.
// file engine.hpp
namespace render {
void Initialise();
namespace inits {
bool glfw_init = false, // these variables will be emitted with
glfw_window_init = false, // every source file that
gl_init = false; // #include "engine.hpp"
}
}
will lead to errors ("mulitply defined symbols") at linking/loading. To avoid that you may declare the variables extern or use functions for setting/getting the state (stored in a variable defined in engine.cpp).
Here is the error I am receiving when running the project that I am using the DLL in:
The odd thing is that this was working at one point. I took a break from this project for a while and now it is not working. Not much has changed besides changing a couple of the parameters.
My setup includes a project in which I build the DLL. This project is then used in a solution with another project that I use to test it. I followed this example: https://msdn.microsoft.com/en-us/library/ms235636.aspx in which I also followed the first time and had it working, now it has stopped.
After realizing it seems to be only one of the functions that is causing the problem I have removed all of the extra code, tried renaming the function, removing everything in it and it is STILL not working.
You can see the function definitions and signatures to see how I am attempting to get this to work below
I have also tried using the "SCOREINTERFACECPP" macro I created on the function instead of the class and I get the same error.
In the project I am testing it in I added the DLL project as a reference and a dependent project, then imported the header file. The other functions I have in the dll (that I have removed from this code for simplicity sake) seem to be working.
Header:
#ifdef SCOREINTERFACECPP_EXPORTS
#define SCOREINTERFACECPP __declspec(dllexport)
#else
#define SCOREINTERFACECPP __declspec(dllimport)
#endif
#include <time.h>
#include <queue>
namespace ScoreInterfaceCPP
{
class SCOREINTERFACECPP ScoreInterface
{
public:
ScoreInterface();
~ScoreInterface();
static void SubmitLogin(const std::string &displayName, const std::string &password);
static void Shutdown();
static SIEvent* GetNextEvent();
static void ClearEvents();
static int GetEventCount();
private:
static std::queue< SIEvent* > mSIEvents;
static bool mGameIsAuthorized;
static std::string mGameName;
static std::string hexedKey;
static std::wstring mAddress;
static void SubmitEventString(std::string eventString);
static int SubmitWithNewThread(void* data);
static void PostMessage(std::string data, std::string iv);
};
}
Source:
#include <sstream>
#include <SDL/SDL_thread.h>
#include <boost/tokenizer.hpp>
#include "ScoreInterfaceCPP.h"
#include "Network.h"
using namespace ScoreInterfaceCPP;
/*
ScoreInterfaceCPP.h
Handles the sending and receiving of events.
*/
ScoreInterface::ScoreInterface()
{
}
ScoreInterface::~ScoreInterface()
{
}
void ScoreInterface::SubmitLogin(const std::string &displayName, const std::string &password)
{
}
void ScoreInterface::SubmitEventString(std::string eventString)
{
}
int ScoreInterface::SubmitWithNewThread(void* data)
{
return 0;
}
SIEvent* ScoreInterface::GetNextEvent()
{
return NULL;
}
int ScoreInterface::GetEventCount()
{
return 0;
}
void ScoreInterface::ClearEvents()
{
}
void ScoreInterface::Shutdown()
{
}
Test file:
#include "ScoreInterfaceCPP.h"
using namespace ScoreInterfaceCPP;
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
ScoreInterface si = ScoreInterface();
si.SubmitLogin("noplayer", "nopassword");
return 0;
}
In my experience, usually problems of this type come with two things you should check (assuming the DLL was built successfully):
Check that the DLL being loaded at runtime is the correct version.
Ensure that the function in question is actually exported.
For the first issue, you can use a utility such as Process Explorer and look at the DLL handles that are loaded for your running exectuable. If you are using Visual C++, you can also look at the Output Window listing of the DLL's that are loaded, and ensure that the version you're using is being loaded.
Many times during development, you may have several (either by accident or by design) versions of your DLL lying in a directory that is accessible by Windows (see DLL Search Order), and thus an old or different version of your DLL is being loaded when you run your application.
For the second issue, there is dumpbin.exe, but I find the Dependency Walker a little more friendly to use. These utilities will show you the functions that are exported from the DLL.
If it is discovered that the function was not exported, then you need to rebuild your DLL, ensuring that __declspec(dllexport) has been used on the function or class you're exporting.
I'm making my first attempt at unit testing in C++, and I haven't used C++ in a number of years (I'm mainly a C# coder at the moment). It seems like I'm making a right pig's ear of it - I hope someone can steer me back onto the righteous path. I'm just getting started here and would really like to be implementing these tests using the best practice possible, so any and all comments are welcome, even though I'm most concerned with my linker error at present.
So, I have an overall solution "Technorabble", with sub-projects "CalibrationTool" and "CalibrationToolUnitTests".
CalibrationTool has a MathUtils.h file:
#ifndef __math_utils__
#define __math_utils__
#include "stdafx.h"
#include <vector>
namespace Technorabble
{
namespace CalibrationTool
{
double GetDoubleVectorAverage(std::vector<double> v)
{
double cumulativeValue = 0;
for(std::vector<double>::iterator iter = v.begin(); iter != v.end(); ++iter)
{
cumulativeValue += *iter;
}
return cumulativeValue / v.size();
}
}; // end namespace CalibrationTool
}; // end namespace Technorabble
#endif // !__math_utils__
(But no .cpp file as I was having all kinds of (somewhat similar) issues getting my template function working - so I ended up defining that inline).
Moving on to the Unit Tests project, I have a main.cpp:
#include "MathUtilsTest.h"
void RunMathUtilsTests();
int main()
{
RunMathUtilsTests();
// Other class tests will go here when I have things to test
}
void RunMathUtilsTests()
{
MathUtilsTest* mathUtilsTest = new MathUtilsTest();
mathUtilsTest->RunTests();
delete mathUtilsTest;
}
Finally, the header and cpp for the MathUtilsTest class, again, fairly simple:
.h:
#ifndef __MATH_UTILS_TEST__
#define __MATH_UTILS_TEST__
#include "CalibrationToolUnitTestsLogging.h"
#include "..\CalibrationTool\MathUtils.h"
class MathUtilsTest
{
public:
MathUtilsTest();
~MathUtilsTest();
bool RunTests();
private:
bool GetDoubleVectorAverageTest();
}; // end class MathUtilsTest
#endif
.cpp:
#include "MathUtilsTest.h"
#include <sstream>
bool MathUtilsTest::RunTests()
{
return GetDoubleVectorAverageTest();
}
MathUtilsTest::~MathUtilsTest()
{
}
MathUtilsTest::MathUtilsTest()
{
}
bool MathUtilsTest::GetDoubleVectorAverageTest()
{
bool passed = true;
std::vector<double> values;
for (int i = 1; i < 23; i++)
{
values.push_back(i);
}
// vector becomes: 1, 2, 3, 4, .....20, 21, 22. Average is 11.5
double expectedAverage = 11.5;
double calculatedAverage = Technorabble::CalibrationTool::GetDoubleVectorAverage(values);
if (calculatedAverage != expectedAverage)
{
std::ostringstream s;
s << calculatedAverage;
std::string avgString = s.str();
CalibrationToolUnitTestsLogging::Write("Failed MathUtilsTest.GetDoubleVectorAverageTest: " + avgString);
passed = false;
}
else
{
CalibrationToolUnitTestsLogging::Write("Passed MathUtilsTest.GetDoubleVectorAverageTest");
}
return passed;
}
This all seemed fine to me, I'm protecting my header with #ifndef, etc. But I'm still getting the following errors:
1) error LNK1169: one or more multiply defined symbols found
2) error LNK2005: "double __cdecl Technorabble::CalibrationTool::GetDoubleVectorAverage(class std::vector >)" (?GetDoubleVectorAverage#CalibrationTool#Technorabble##YANV?$vector#NV?$allocator#N#std###std###Z) already defined in main.obj C:_SVN\Technorabble\Windows Software\CalibrationToolUnitTests\MathUtilsTest.obj
How can this be? Can anyone spot where it's going wrong?
Functions defined in headers should be marked as inline:
inline double GetDoubleVectorAverage(std::vector<double> v)
{
}
If it's longer than a couple of lines, consider moving it to an implementation file.
pragmas or include guards don't protect against multiple definitions.
Note that you should pass v by const reference rather than by-value.
You are defining a function GetDoubleVectorAverage in a header. This means that it will be defined in every translation unit (i.e. every source file) that includes that header. If your program contains more than one such translation unit, then you'll have more than one definition - which isn't allowed.
Solutions are:
Add inline to the function definition, to relax this rule and allow multiple identical definitions; or
Move the function definition into a source file, and only declare it in the header.
I'm protecting my header with #ifndef
That only prevents the header from being included more than once within the same translation unit. It doesn't prevent inclusion from more than one unit.
Also, you shouldn't use a reserved name like __math_utils__ as a header guard, even if the internet is littered with examples of dodgy code doing that.
I was having all kinds of (somewhat similar) issues getting my template function working
Templates usually need to be defined in header files, to make the definition available at the point of use. Function templates are implicitly inline, but normal functions (like this one) aren't.
I am writing file conversion code from a proprietary file format to one more generic. My goal is to support multiple versions of the manufacturer's file format.
I have a multiple versions of the same proprietary headers. The headers define various structs which comprise the main file header (the file is simply a large header followed by raw data).
I need to read the first 4 bytes of the source file to determine the file version. The file version, in turn, tells me which version of the C-structs was used to create the file.
The issues are:
I can't modify the proprietary headers
The headers do not use namespaces or classes
There are a good handful of macros defined in the headers
Possible solutions:
Build different converter binaries for each file version type :-(
Inconvenient for both user and developer
Dynamically load libraries for each version
The converter is plugin-oriented, so there's already a lot of this happening
I have tried hacking with namespaces:
namespace version1 {
#include "version1.h"
}
namespace version2 {
#include "version2.h"
}
int main (void) {
version1::header *hdr = new version1::header;
return 0;
}
But this won't work because of include guards, and because there are multiple macros are redefined in each header.
Is there an elegant way to handle this?
You could use two different source files, together with a forward declaration:
// Forward declare in main.cpp:
namespace version1
{
struct header;
}
namespace version2
{
struct header;
}
// version1.cpp:
namespace version1
{
#include <version1.h>
}
version1::header* new_v1_header()
{
return new version1::header;
}
// other functions using `version1::header`
// version2.cpp:
namespace version2
{
#include <version2.h>
}
version2::header* new_v2_header()
{
return new version2::header;
}
// other functions using `version2::header`
Another alternative is to implement a wrapper class, which has a base-class that is just an empty shell:
class header_base
{
virtual int func1(char *stuff) = 0;
... many other virtual functions.
};
// Create implementation of header_v1 or header_v2:
header_base* make_header(unsigned int magic);
header_base.cpp:
#include "header_v1.h"
#include "header_v2.h"
header_base* make_header(unsigned int magic)
{
switch(magic)
{
case Magic_V1:
return new header_v1;
case Magic_V2:
return new header_v2;
default:
assert(0);
return 0;
}
}
and then implement, in two separate
in headerv1.h:
class header_v1 : public header_base
{
int func1(char *stuff);
...
};
header_v1.cpp:
#include "header1.h"
int header_v1::func1(char *stuff)
{
...
return 17;
}
And similar for header_v2.h and header_v2.cpp.