I have the following config to evaluate and am using a factory to get an object to a subclass of MathOperation based on type.
class MathOperation {
Operation GetOperationType();
int Evaluate (config c);
}
config {
type = min
config {
type = average
int x
int y
}
config {
type = sum
int p
int q
}
...
}
For instance if x = 10, y = 20, p = 10, q = 2
the answer is min(average(10, 20), sum(10, 2)) = 12.
I am running into a circular dependency issue because each subclass of MathOperation needs to include the factory to evaluate it's subconfig and the factory ofcoruse needs to include each subclass of MathOperation. How do I resolve this?
This is what I currently have:
MathOperationFactory.h and cc
#include "average.h"
#include "min.h"
#include "sum.h"
std::unique_ptr<MathOperationObject> MakeObject(OperationType type) {
switch(type) {
case min : return MinOperation();
...
}
}
MinOperation.h and cc
#include "mathoperationfactory.h"
int Evaluate(Config c) {
int minimum = 1000; // large number.
ASSERT(config.type = min);
for(config : c) // repeated configs {
type t = c.type;
factory.MakeObject(t);
if(t.Evaluate < minimum) {
minimum = t;
}
}
return minimum;
}
The Factory doesn't need to know the subtype, it just needs to be able to new one up. One way to do this is with a Creator class whose job is to delegate the creation of the concrete object back to the class itself.
I'm using std::string here for names, but you could easily use int or Operation enum.
Something like:
#pragma once
#include <string> //
#include <map>
#include <typeinfo>
class MathOperation;
/************************************************************************/
/* MathOperation Factory */
/************************************************************************/
// Abstract Interface Type For Creator
struct CMathOperationCreator
{
virtual MathOperation* Create() = 0;
virtual ~CMathOperationCreator() {}
};
// Creator Map
std::map<std::string, CMathOperationCreator*, StringLessNoCaseCHAR>& GetMathOperationFactoryMap();
// Templated concrete creator, to be registered in the header of the concrete mathop type
template<class Derived>
struct CMathOperationConcreteCreator: public CMathOperationCreator
{
CMathOperationConcreteCreator(const std::string& theMathOperationTypeId)
{
auto aFactoryItem = GetMathOperationFactoryMap().find(theMathOperationTypeId);
if(aFactoryItem != GetMathOperationFactoryMap().end())
{
if(typeid(*aFactoryItem->second) == typeid(*this)) // avoid duplicates
return;
}
GetMathOperationFactoryMap()[theMathOperationTypeId] = this;
}
virtual MathOperation* Create() {return new Derived();}
};
//Factory Method
MathOperation* CreateMathOperation(const std::string& theMathOperationTypeId);
/**
* Macro to automatically register a MathOperation Type
*/
#define REGISTER_MathOperation( ConcreteMathOperation, name ) \
static CMathOperationConcreteCreator<ConcreteMathOperation> ConcreteMathOperation##Creator(name);
The CPP file:
// This is dumb, you don't have to do this, you just need a singleton factory that holds this map
std::map<std::string, CMathOperationCreator*, StringLessNoCaseCHAR>& GetMathOperationFactoryMap()
{
static std::map<std::string, CMathOperationCreator*, StringLessNoCaseCHAR> theMap;
return theMap;
}
MathOperation* CreateMathOperation( const std::string& theMathOperationTypeId )
{
auto aFactoryItem = GetMathOperationFactoryMap().find(theMathOperationTypeId);
if (aFactoryItem != GetMathOperationFactoryMap().end())
{
MathOperation* aObject = aFactoryItem->second->Create();
return aObject;
}
return NULL;
}
Register a class:
class MinOperation : public MathOperation {
Operation GetOperationType();
int Evaluate (config c);
};
REGISTER_MathOperation(MinOperation, "min");
Then, when you're parsing your tokens, you can query the factory for the operation:
MathOperation* pOp = CreateMathOperation(token.lowercase());
As pointed out in the comments, it's hard to be sure without seeing real code. However, most likely the issue is you are putting too many includes in the header files. if you just add #include "mathoperationfactory.h" in the cc file, you should be fine.
Also, you need to use include guards.
#pragma once makes sure that a header is only included once. Always put this as your first line in headers.
Related
I want to wrap a class derived from std::vector with some extend functions into csharp with swig. the functions from vector are also needed like push_back to add new item into the class (which named Add in csharp).
I tried with default setting with swig, IntArray is valid in csharp .But, vector's functions are invalid.
if i try to define a vector in the .i file:
namespace std{
%template(ScalarVec) vector<ScalarTest>;
}
a class named ScalarVec have functions like vector is valid in csharp, but without the extend function.
How to wrap the ScalarArray to csharp with swig?
The following is a simple example.
#include <vector>
#include <numeric>
namespace test
{
struct ScalarTest {
int val;
};
struct ScalarArray : public std::vector<ScalarTest>
{
int sum() const {
int res = 0;
for (const ScalarTest &item : *this) {
res += item.val;
}
return res;
}
};
}
SWIG is picky about order of declarations. Below correctly wraps your example code and can call the sum function. I'm not set up for C# so the demo is created for Python:
test.i
%module test
%{
// Code to wrap
#include <vector>
#include <numeric>
namespace test
{
struct ScalarTest {
int val;
};
struct ScalarArray : public std::vector<ScalarTest>
{
int sum() const {
int res = 0;
for (const ScalarTest &item : *this) {
res += item.val;
}
return res;
}
};
}
%}
namespace test
{
struct ScalarTest {
int val;
};
}
%include <std_vector.i>
// Must declare ScalarTest above before instantiating template here
%template(ScalarVec) std::vector<test::ScalarTest>;
// Now declare the interface for SWIG to wrap
namespace test
{
struct ScalarArray : public std::vector<ScalarTest>
{
int sum() const;
};
}
demo.py
import test
x = test.ScalarArray()
a = test.ScalarTest()
a.val = 1
b = test.ScalarTest()
b.val = 2
x.push_back(a)
x.push_back(b)
print('sum',x.sum())
print(x[0].val,x[1].val)
Output:
sum 3
1 2
I'm trying to implement a class (C++) with an enum (with the permitted parameters). I got a working solution, but if I try to extend the functionality I get stuck.
Header data_location.hpp
class DataLocation
{
private:
public:
enum Params { model, period };
std::string getParamString(Params p);
};
Program data_location.cpp
string DataLocation::getParamString(Params p){
static const char * ParamsStrings[] = {"MODEL", "PERIOD"};
return ParamsStrings[p];
}
The array ParamsStrings should be generally available in the class, because I need a second method (with inverse function) returning the enum value given a string.
If I try to define the array in the header I get the error:
in-class initialization of static data member ‘const char* DataLocation::ParamsStrings []’ of incomplete type
Why is the type incomplete? The compiler is for sure able to counts the strings in the array, isn't it?
In case there is no way to get my code working, is there an other way? With 1) no XML; 2) no double definition of the strings; 3) not outside the class; 4) no in code programmed mapping.
In class (header) use keyword static and initialize it outside (.cpp) without the static keyword:
class DataLocation {
public:
enum Params { model, period };
string getParamString(Params p);
static const char* ParamsStrings[];
// ^^^^^^
};
const char* DataLocation::ParamsStrings[] = {"MODEL", "BLLBLA"};
//^^^^^^^^^^^^^^^^^^^^^^^^
The code you have posted is perfectly fine.
Here's the proof:
#include <iostream>
#include <string>
struct DataLocation
{
enum Params { model, period };
std::string getParamString(Params p){
static const char * ParamsStrings[] = {"MODEL", "PERIOD"};
return ParamsStrings[p];
}
};
int main()
{
auto a = DataLocation();
std::cout << a.getParamString(DataLocation::model) << std::endl;
return 0;
}
The error message you are getting is not to do with definition of a static data member in an inline function - that's allowed.
There's something else you're not showing us.
The main issue in my question (the second part) was that if I split the class in .hpp and .cpp the definition of the array (I mixed *char and string) has also to be split:
// data_location.hpp
class DataLocation {
static const char * ParamsStrings[];
}
// data_location.cpp
const char * ParamsStrings[] = {"MODEL", "PERIOD"};
At the end I introduced a consistency check to be sure that the number of values in enum growths as the number of strings. Because the array in C++ is somehow limited I had to go for a std::vector (to get the size).
Code for data_location.hpp
#ifndef DATA_LOCATION_HPP_
#define DATA_LOCATION_HPP_
#include <string>
#include "utils/dictionary.hpp"
extern const char* ENV_DATA_ROOT;
struct EDataLocationInconsistency : std::runtime_error
{
using std::runtime_error::runtime_error;
};
struct EDataLocationNotValidParam : std::runtime_error
{
using std::runtime_error::runtime_error;
};
class DataLocation
{
private:
std::string mRootLocation;
static const std::vector<std::string> msParamsStrings;
static bool msConsistenceCheckDone;
public:
DataLocation();
std::string getRootLocation();
std::string getLocation(Dictionary params);
enum Params { model, period, LAST_PARAM};
std::string Param2String(Params p);
Params String2Param(std::string p);
};
#endif
Code for data_location.cpp
#include "data_location.hpp"
#include <string>
#include <cstdlib>
using namespace std;
const char* ENV_DATA_ROOT = "DATA_ROOT";
bool DataLocation::msConsistenceCheckDone = false;
DataLocation::DataLocation() {
mRootLocation = std::getenv(ENV_DATA_ROOT);
if (not msConsistenceCheckDone) {
msConsistenceCheckDone = true;
if (LAST_PARAM+1 != msParamsStrings.size()) {
throw(EDataLocationInconsistency("DataLocation: Check Params and msParamsStrings"));
}
}
}
string DataLocation::getRootLocation() {
return mRootLocation;
}
string DataLocation::getLocation(Dictionary params) {
// to do
return "";
}
const vector<string> DataLocation::msParamsStrings = { "MODEL", "PERIOD", ""};
string DataLocation::Param2String(Params p) {
if (p>=msParamsStrings.size()) {
throw(EDataLocationNotValidParam("Parameter not found"));
}
return msParamsStrings[p];
}
DataLocation::Params DataLocation::String2Param(string p) {
for (int i = 0; i < msParamsStrings.size(); i++) {
if (p == msParamsStrings[i])
return (Params)i;
}
throw(EDataLocationNotValidParam("Parameter not found"));
}
And also a unit test:
#include <boost/test/unit_test.hpp>
#include "data_location.hpp"
#include <string>
using namespace std;
BOOST_AUTO_TEST_SUITE( data_location )
BOOST_AUTO_TEST_CASE(data_location_1) {
DataLocation dl;
auto s = dl.getRootLocation();
BOOST_CHECK_EQUAL(s, "/home/tc/data/forex" );
BOOST_CHECK_EQUAL(dl.Param2String(DataLocation::period),"PERIOD");
BOOST_CHECK_EQUAL(dl.String2Param("PERIOD"),DataLocation::period);
BOOST_CHECK_THROW(dl.String2Param("SOMETHING"), EDataLocationNotValidParam);
BOOST_CHECK_THROW(dl.Param2String((DataLocation::Params)100), EDataLocationNotValidParam);
}
BOOST_AUTO_TEST_SUITE_END()
C++ is very picky about what it will let you initialize inside of a class definition; there are some particularly non-intuitive rules surrounding static members. It all has to do with the ODR, and why all the rules are the way they are is not especially important.
To cut to the chase, making your array a static constexpr const member should shut the compiler up. With the C++11 standard, the restrictions were relaxed a bit, and one of the new stipulations was that static constexpr members can be initialized inline. This is perfect for your application, since the strings in your array are compile-time constants.
The recent g++ compiler which support C++0x or later compiles thus code. Pure C compile compiles, too. Because strings in initialization like {"MODEL", "PERIOD"}; implemented as const char * pointer to the char array.
The idea is identical to the generic version of GetComponent() in Unity. But I'm currently stumbling on the following template issue:
template<class T> std::shared_ptr<T> MyClass::GetMyComponent()
{
for (int i = 0; i < _baseTypeList.size(); i++)
{
auto base = _baseTypeList[i];
T* check = dynamic_cast<T*>(base.get());
if (check)
{
return std::static_pointer_cast<T>(base);
}
}
return std::shared_ptr<T>(nullptr);
}
where _baseTypeList is a std::vector<std::shared_pntr{MyBaseType}> types.
In this function, I am iterating over a list of components to find if there is one that matches the type I'm asking for. if there is one, return the component cast to that type. Otherwise return a nullptr.
However, when I call this function from outside code, I get the following error:
error C2680: 'MyType*' : invalid target type for dynamic_cast
where MyType is some class that derives from component.
When I put #include "MyType.h" in the header it compiles just fine but without it it gives this error and doesn't compile.
This means I cannot use it in other classes without modifying the header file this template class resides in, which will be a problem for me.
Is there a way I can achieve simular results without having to #include every single header of the type I pass in the template for?
[EDIT]
For clarity, consider a person using my library, he creates a type
"Foo : MyBaseType" where MyBaseType has a virtual method "Update" that is called every frame.
any instance of class MyBaseType (including Foo) is to be managed by this library, and have update called every frame.
This library thus has a large list of "MyBaseType" objects. But has no knowledge of the actual type they are, just that they derive from "MyBaseType", so it can call Update() on them.
If I need a specific type the library needs to be able to search for it in this list and return it.
I would like this "search" to happen in the library itself, so I do not have to expose the list, and write a new "search" method for every type that derives from "MyBaseType"
[FINAL]
It turned out I messed up the include order in my project.
a minimal example of what I was trying to do would be:
#include <stdio.h>
#include <tchar.h>
#include <iostream>
#include <memory>
#include "vector"
class MyBaseClass
{
virtual void Update(){};
};
class MyLibrary
{
public:
template<class T> std::shared_ptr<T> GetComponent();
std::vector<std::shared_ptr<MyBaseClass>> list;
};
template<class T> std::shared_ptr<T> MyLibrary::GetComponent()
{
static_assert(std::is_base_of<MyBaseClass, T>::value, "T1 is no subclass of ModelComponent");
for (unsigned int i = 0; i < list.size(); i++)
{
auto comp = list[i];
T* check = dynamic_cast<T*>(comp.get());
if (check)
{
return std::static_pointer_cast<T>(comp);
}
}
return std::shared_ptr<T>(nullptr);
}
class MyClass : public MyBaseClass
{
void Update() override;
};
void MyClass::Update()
{
}
int _tmain(int argc, _TCHAR* argv[])
{
MyLibrary lib;
lib.list.push_back(std::make_shared<MyClass>());
auto var = lib.GetComponent<MyClass>();
std::cout << (var ? "var is object" : "var is not") << std::endl;
while (true)
{
}
return 0;
}
which works as expected.
The primary issue was that the compiler gave an error in the "GetMyComponent" function, so I found a usage of it that did everything as suggested.
But it turned out there was a second usage that did not have the definition of "MyClass" before calling it (but didn't give an error, as it was forward declared in its header file).
You don't need the definition of possible T types included into your header. You do need the relevant one defined in the translation unit in which the template is expanded:
// client.cpp
#include <myclass.h>
#include <foo.h> // defines class Foo
void f(MyClass *p)
{
auto c = p->GetMyComponent<Foo>();
c->foobar();
}
I have a function like the following:
//Parser.cpp
//...
Parser::Parser(CommandFactory & fact,
ArrayList<std::string> & expression)
{
operations["*"] = &fact.createMultiplyCommand; //error C2276
operations["/"] = &fact.createAdditionCommand; //error C2276
operations["+"] = &fact.createAdditionCommand; //error C2276
operations["%"] = &fact.createModulusCommand; //error C2276
operations["-"] = &fact.createSubtractionCommand; //error C2276
infixToPostfix(fact,expression);
}
//...
//Parser.h
//...
Parser (CommandFactory & fact,
ArrayList<std::string> & expression);
Stack<Command*> tempCommandStack;
ArrayList<Command*> postfix;
/// Destructor.
~Parser (void);
private:
//syntax is: <return_type> (*)()
//syntax for a class method is: <return_type> (<class_name> *)();
//syntax with a typedef is: typedef <return_type> (<class_name> * <typedef_name>)();
// typedef <return_type> (*<typedef_name>)()
std::map<std::string, Command * (*)()> operations;
std::map<std::string,int> precedence;
//...
It also may help to know that CommandFactory is an abstract class (what is passed in is concrete)
The error I receive is C2276: '&' : illegal operation on bound member function expression.
I don't know what I'm doing wrong exactly when I define the mapping. Any ideas?
EDIT:
//CommandFactory.h
#ifndef _COMMANDFACTORY_H_
#define _COMMANDFACTORY_H_
#include "Subtract.h"
#include "Add.h"
#include "Divide.h"
#include "Multiply.h"
#include "Modulus.h"
#include "Negation.h"
class CommandFactory
{
public:
virtual Subtract * createSubtractionCommand() = 0;
virtual Add * createAdditionCommand() = 0;
virtual Divide * createDivisionCommand() = 0;
virtual Multiply * createMultiplyCommand() = 0;
virtual Modulus * createModulusCommand() = 0;
virtual Negation * createNegationCommand() = 0;
~CommandFactory(void);
};
#endif
//StackCommandFactory.h
#ifndef _STACKCOMMANDFACTORY_H_
#define _STACKCOMMANDFACTORY_H_
#include "Add.h"
#include "Subtract.h"
#include "Divide.h"
#include "Multiply.h"
#include "Modulus.h"
#include "CommandFactory.h"
class StackCommandFactory : public CommandFactory
{
public:
virtual Subtract * createSubtractionCommand(void);
virtual Add * createAdditionCommand(void);
virtual Divide * createDivisionCommand(void);
virtual Multiply * createMultiplyCommand(void);
virtual Modulus * createModulusCommand(void);
virtual Negation * createNegationCommand(void);
protected:
Subtract * sub;
Add * add;
Divide * div;
Multiply * mul;
Modulus * mod;
Negation * neg;
};
#endif // !defined _STACKCOMMANDFACTORY_H_
//StackCommandFactory.cpp
#include "StackCommandFactory.h"
Subtract * StackCommandFactory::createSubtractionCommand(void)
{
return sub;
}
Add * StackCommandFactory::createAdditionCommand(void)
{
return add;
}
Divide * StackCommandFactory::createDivisionCommand(void)
{
return div;
}
Multiply * StackCommandFactory::createMultiplyCommand(void)
{
return mul;
}
Modulus * StackCommandFactory::createModulusCommand(void)
{
return mod;
}
Negation * StackCommandFactory::createNegationCommand(void)
{
return neg;
}
There's a few issues with your code. Mostly centring about the use of member functions rather than global functions. You try to get the member functions from an object, where you should be getting them from the class itself. ( i.e. instead of &fact.createAdditionCommand you need &CommandFactory::createAdditionCommand.) But this results in an unbound member function, which means you need to call it using (fact.*fn)() - i.e. with an object of the CommandFactory class. This is not ideal - and not what you're looking for. You are looking for a bound member function. Using these in non C++-11 applications is possible, but ugly.
You can use boost libraries to really help with that (and the code below will pretty much work unchanged other than some std to boost style changes.) If you're using C++-11 then you can use the C++-11 function objects.
Here's a complete example derived from your source:
#include <vector>
#include <map>
#include <functional>
#include <string>
struct Command {};
struct Subtract : Command {};
struct Add : Command {};
class CommandFactory
{
public:
virtual Subtract * createSubtractionCommand() = 0;
virtual Add * createAdditionCommand() = 0;
};
class StackCommandFactory : public CommandFactory
{
public:
virtual Subtract * createSubtractionCommand(void);
virtual Add * createAdditionCommand(void);
Subtract * sub;
Add * add;
};
Subtract * StackCommandFactory::createSubtractionCommand(void) { return sub; }
Add * StackCommandFactory::createAdditionCommand(void) { return add; }
class Parser
{
public:
Parser (CommandFactory & fact);
std::map<std::string, std::function<Command*()> > operations;
};
Parser::Parser(CommandFactory & fact)
{
operations["+"] = std::bind(&CommandFactory::createAdditionCommand, &fact);
operations["-"] = std::bind(&CommandFactory::createSubtractionCommand, &fact);
}
#include <iostream>
int main()
{
Add add;
Subtract sub;
StackCommandFactory command_factory;
command_factory.add = &add;
command_factory.sub= ⊂
Parser parser(command_factory);
std::cout<<"&add = "<<&add<<std::endl;
std::cout<<"Add = " << parser.operations["+"]() <<std::endl;
std::cout<<"&sub = "<<&sub<<std::endl;
std::cout<<"Sub = " << parser.operations["-"]() <<std::endl;
return 0;
}
I get the output
&add = 0x7fff58d538d8
Add = 0x7fff58d538d8
&sub = 0x7fff58d538d0
Sub = 0x7fff58d538d0
Showing that the Add object returned by going through the parser is the same as that stored into the CommandFactory. (And same for the Subtract object)
You can't do it in standard C++. For reasons have a look here & here.
EDIT:
Instead of storing "Command * (*)()" into operations, why not change "operations" value type to store "Command *" ? Or perhaps have a relook into the low-level design?
sorry try
operations["*"] = fact.createMultiplyCommand;
or
operations["*"] = fact->createMultiplyCommand;
In the below programme i use one boolean variable named check , which is being accessed inside main function by two objects of Tst1 and Test2 . But the value of check variable is not maintained in the programme . we can use static but i want to know some alternative way ..could anyone give me some hints on it ?
Thanks in advance .
Inside jointdeatils.h
#pragma once
class Jointdetails
{
public:
Jointdetails(void);
~Jointdetails(void);
bool check;
};
Inside jointdeatils.cpp
#include "Jointdetails.h"
Jointdetails::Jointdetails(void)
{
check = false ;
}
Jointdetails::~Jointdetails(void)
{
}
Inside analyzer.h
#pragma once
#include "Jointdetails.h"
class Analyzer
{
public:
Analyzer(void);
Jointdetails* GetJointDetails();
Jointdetails* m_ptheCTJointDetails;
~Analyzer(void);
};
Inside analyzer.cpp
#include "Analyzer.h"
#include "stddef.h"
Analyzer::Analyzer(void)
{
m_ptheCTJointDetails = new Jointdetails();
}
Analyzer::~Analyzer(void)
{
}
Jointdetails* Analyzer::GetJointDetails()
{
if(m_ptheCTJointDetails)
return m_ptheCTJointDetails;
else
return NULL;
}
Inside Test1.h
#pragma once
#include "Analyzer.h"
class Tst1
{
public:
Tst1(void);
Analyzer *analyzer1 ;
public:
~Tst1(void);
};
Inside Test1.cpp
#include "Tst1.h"
Tst1::Tst1(void)
{
analyzer1 = new Analyzer ;
}
Tst1::~Tst1(void)
{
}
Inside Test2.h
#pragma once
#include "Analyzer.h"
class Test2
{
public:
Test2(void);
Analyzer *analyzer2 ;
public:
~Test2(void);
};
Inside Test2.cpp
#include "Test2.h"
Test2::Test2(void)
{
analyzer2 = new Analyzer ;
}
Test2::~Test2(void)
{
}
Inside main.cpp
#include "Test2.h"
#include "Tst1.h"
#include "stdio.h"
int main()
{
Tst1 *test1 = new Tst1 ; //check = false
Test2 *test2 = new Test2 ; //check = false
test1->analyzer1->GetJointDetails()->check = true ;
if(test2->analyzer2->GetJointDetails()->check )
printf("Check value is changed");
else
printf("Check value is not changed");
return 0 ;
}
There are only two possible ways to do so:
Use static storage data
Pass automatic or dynamic storage data as parameters to destination functions/ctors
Way #1 is more handy as you can access such data directly from any function. But it shall be considered as bad design because it almost the same thing as evil global variables.
Way #2 is more correct (see answer by justin for example) but could be a bit irritating - you will need to pass required data as parameter to each required function and/or store data as class data member. Not a pleasant work in case of many classes/nested calls.
Nevertheless, if you don't care on drawbacks of way #1 consider singleton-on-demand concept. It allows to use static data in more dynamic way - create on demand, share access by several users and destroy when nobody use it anymore. See example (several details, includes etc skipped for brevity):
JointDetails.h
class JointDetails
{
// Actual class definition
// ...
public:
// Function accessing to JointDetails instance
static std::shared_ptr<JointDetails> Get();
};
JointDetails.cpp
std::shared_ptr<JointDetails> JointDetails::Get()
{
static std::weak_ptr<JointDetails> s_trackInstance;
if(s_trackInstance.expired())
{
auto instance = std::make_shared<JointDetails>();
s_trackInstance = instance;
return instance;
}
return s_trackInstance.lock();
}
Analyzer.h
// All instances of Analyzer share the same instance of JointDetails.
// But JointDetails instance is created dynamically only when first instance of
// Analyzer is created and destoyed when the last instance of Analyzer is destroyed.
class Analyzer
{
std::shared_ptr<JointDetails> m_details;
public:
Analyzer(): m_details(JointDetails::Get()) {}
const JointDetails& GetDetails() const { return *m_details; }
};
You're either going to have to make check static, or JointDetails a singleton (which also uses the static keyword).
If you make check static, you are saying that all instances of JointDetails have the same check.
If you make JointDetails a singleton, then you're saying that every reference to a JointDetails object is the same object, so your Tst1 and your Test2 will both have a pointer to the same object.
I think the latter is what you're looking for:
Jointdetails.h
#pragma once
class Jointdetails
{
public:
~Jointdetails(void);
bool check;
static Jointdetails* getInstance();
private:
Jointdetails(void);
};
Jointdetails.cpp
#include "Jointdetails.h"
Jointdetails::Jointdetails(void)
{
check = false ;
}
Jointdetails::~Jointdetails(void)
{
}
Jointdetails* Jointdetails::getInstance() {
static Jointdetails s_instance;
return &s_instance;
}
Analyzer.cpp
Analyzer::Analyzer(void)
{
m_ptheCTJointDetails = Jointdetails::getInstance();
}
0) you needn't use new so often.
1) you can construct your objects with the joint details as a parameter in your constructor.
To illustrate:
class Tst1 {
public:
Tst1(Jointdetails& pJointdetails) : analyzer1(pJointdetails) {
}
Analyzer analyzer1;
public:
~Tst1(void);
};
int RunProgram(Jointdetails& pJointdetails) {
Tst1(pJointdetails);
...
}
int main() {
Jointdetails jointdetails;
const int result(RunProgram(jointdetails));
return result;
}