currently I switch from Java to C++ and this is giving me a hard time (but lots of new experience ^^). I'm writing some data-transfer-objects which contain configurations for my program. I've written some classes and now I want to have a class which behaves like a container.
Here's a header for the container:
class MyContainer{
public:
MyContainer();
virtual ~MyContainer();
Config getConfig(TypeEnum type) {
switch (type) {
case ATYPE:
return config_a;
case BTYPE:
return config_b;
default:
break;
}
}
ConfigA config_a;
ConfigB config_b;
};
The configs have some data in it and are derived from another config-file.
And here is the C++-Source:
MyContainer::MyContainer(){
ConfigA config_a(int c = 1);
ConfigB config_b(double b = 2.1);
this->config_a = config_a;
this->config_b = config_b;
}
There are several problems I think. But the main question for me is:
How can I get those configs in this container to share it to other modules of my program? I have tried to make config_a to a pointer but I always get error-messages that these types won't match.
this->config_a = &config_a; //If ConfigA config_a; was ConfigA *config_a; instead
If you have another minute for me then please tell me if the getConfig-Method could work like this.
And if there's another topic for this then please share. Thanks.
If you write ConfigA configA in your header, the configA is automatically allocated during the allocation of the container class. So you don't have to initialize it like following:
ConfigA config_a(1);
this->config_a = config_a;
Instead, you can just do the following:
this->config_a->value = 1;
There is no need to write:
ConfigA config_a(int c = 1);
In short words, the mentioned int c = 1 is an operation, which:
allocates space on heap for temporary variable c (this may be done when entering the method as well)
assigns value to it, which has side effect of returning the right-hand-side value
the returned right-hand-side value is applied to the ConfigA constructor.
To understand this, try the following:
int a, b, c;
c = (a = 2) + (b = 8);
printf("a = %d, b = %d, c = %d\n", a, b, c);
If you want to pass the configs to another modules, you can choose one of the following solutions:
a) Accept the configs as references (the config classes have to derive from the same base class):
ConfigA & configA = dynamic_cast<ConfigA &>(container.get_config(ATYPE));
In this case, container shall return the configs in the following way:
return this->configA;
But the header shall be modified:
Config & getConfig(TypeEnum type) { (...)
b) Accept the configs as pointers (same as above)
ConfigA * configA = dynamic_cast<ConfigA *>(container.get_config(ATYPE));
In this case, container shall return the configs in the following way:
return &(this->configA);
Finally, this is the way I would do it:
class ConfigA
{
private:
int i;
public:
int GetI() const { return i; }
void SetI(int newI) { i = newI; }
};
class ConfigB
{
private:
float f;
public:
float GetF() const { return f; }
void SetF(float newF) { f = newF; }
};
class Config
{
private:
ConfigA configA;
ConfigB configB;
public:
ConfigA & GetConfigA() { return configA; }
ConfigB & GetConfigB() { return configB; }
};
class AppContext
{
private:
Config config;
public:
Config & GetConfig() { return config; }
};
// Somewhere in the code
Config & config = context.GetConfig();
ConfigA & configA = config.GetConfigA();
configA.SetI(44);
The const-correctness is also worth mentioning, but we'll leave it as an exercise for the OP ;)
Your code:
ConfigA config_a(int c = 1);
Means a function prototype that returns ConfigA and takes an int with a default value of 1.
But if you seperate the int declaration from the expression, it will change to something else:
int c;
ConfigA config_a(c = 1); // This is construction of a ConfigA object
I would write the constructor like this:
MyContainer::MyContainer(int c = 1, double d = 2.1)
: config_a (c), config_b (d) // Construct the members in the intialization line
{
}
If you want to share a pointer to these members, return a pointer like this:
ConfigA * MyContainer::GetConfigA(){return &config_a;}
ConfigB * MyContainer::GetConfigB(){return &config_b;}
But if you want to work with pointer members:
MyContainer::MyContainer(int c = 1, double d = 2.1)
: pConfig_a (new ConfigA (c)), pConfig_b (new ConfigB (d))
{
}
ConfigA * MyContainer::GetConfigA(){return pConfig_a;}
ConfigB * MyContainer::GetConfigB(){return pConfig_b;}
MyContainer::~MyContainer()
{
delete pConfig_a;
delete pConfig_b;
}
Related
I would like to obtain an class instance from another class.
I have the following classes, with class A having B object as a private member.
class A
{
private:
B my_B;
public:
B getBInstance (void)
{
return this->my_B;
}
}
class B
{
private:
int my_attr;
public:
B ()
{
this -> my_attr = 0; //Initial value for my_attr
}
void setMyAttr (int attr)
{
this->my_attr = attr;
}
int getMyAttr (void)
{
return this->my_attr;
}
}
I want my_B to be exclusive to an object that is instantiated from class A.
When I perform the following, I am not able to change the contents of my_attr, because it accesses a different B instance everytime I call A::getBInstance().
A new_A;
new_A.getBInstance().setMyAttr(50);
printf ("%d\n", new_A.getBInstance().getMyAttr()); //Prints 0
But, if I do the following, then I get the correct output:
A new_A;
new_B = new_A.getBInstance();
new_B.setMyAttr (50);
printf ("%d\n", newB.getMyAttr()); //Prints 50
I apologize if the answer is so obvious. I suspect efforts regarding making things static or singleton pattern might help, yet I need some guidance, as I'm pretty new to this kind of implementations.
Thanks in advance,
You're returning a copy of my_B. If you want to change the one stored in A, return a reference:
B &getBInstance (void)
{
return this->my_B;
}
I have the following (kinda pseudo) code, which handles 2 containers of 2 different (but somewhat similiar) types, and I hate having these duplications for addition and deletion (and also 2 searching functions in my real code)
class PureAbstractClass
{
public:
virtual char Func() = 0;
}
class PureOpt1 : PureAbstract
{
public:
virtual int FOption1(A, B, C) = 0; // Notice 'C'
}
class PureOpt2 : PureAbstract
{
public:
virtual int FOption2(A, B, D) = 0; // Notice 'D'
}
class Handler
{
public:
void Add(PureOpt1* arg) { v1.add(arg); }
void Add(PureOpt2* arg) { v2.add(arg); }
// This is implemented using lambda
// Sorry for LINQ syntax, lambdas are too long for pseudo code
void Del1(char c) { arg = v1.find(obj => obj->Func() == c); v1.del(arg); }
void Del2(char c) { arg = v2.find(obj => obj->Func() == c); v2.del(arg); }
void Process(ch, A, B, C, D)
{
o1 = v1.Find(obj => obj->Func() == ch);
if( null == o1 )
{
o2 = v2.Find(obj => obj->Func() == ch);
if( null == o2 )
{
DoSomething();
}
else
{
o2->FOption2(A, B, D);
}
}
else
{
o1->FOption1(A, B, C);
}
}
private:
vector<PureOpt1*> v1;
vector<PureOpt2*> v2;
}
Having Handler be a template class is impossible because of Process().
Is there a more correct way to implement this kind of code?
How to correctly manage 2 containers of different types in a class?
Answer is use only 1 container.
Simplest solution would be to have pure vitual method in base class:
class PureAbstractClass
{
public:
virtual char Func() = 0;
virtual int FOption(A, B, C, D) = 0;
}
then both children override FOption() and ignore parameter they do not need. There could be better solution but you do not provide enough information. Your solution - to keep them in 2 separate containers is probably the worst. As you can see your solution conflicts with inheritance (you remove inheritance and make both children independent classes and nothing would change in your code). Alternatively you can use dynamic_cast, but using it usually shows bad program design:
PureAbstractClass *o = find( ... );
if( !o ) {
DoSomething();
return;
}
if( PureOpt1 *po1 = dynamic_cast<PureOpt1 *>( o ) )
po1->FOption1( A, B, C );
else {
if( PureOpt2 *po2 = dynamic_cast<PureOpt2 *>( o ) )
po2->FOption2( A, B, D );
else
// something wrong object is not PureOpt1 nor PureOpt2
}
Note: it is completely unnecessary for FOption1() and FOption2() to be virtual in this case. And you should not forget to add virtual destructor to the base class.
Alternatively you may use boost::variant and visitor patter, in this case you do not need inheritance as well but you can make your code generic.
If possible have the FOption1/2 be int Func(Data const & data). You then create the data and pass it to it. Data can have the four different pieces of information with C and D being optional. The specific implementation of Func can then process that data as it needs
Here is what I am trying to do in C++. From an external library that I use I have 3 classes, MyClass1, MyClass2 and MyClass3 that are identical in their public functions. I would like to decide, at the beginning of runtime, which one will be used by in the rest of my code depending on the hardware configuraion of the user.
To better illustrate what I mean, let me give an example that I know does not work. If it were possible to conditionally define a typedef at runtime, what I am trying to achieve would look as follows:
const int x = GetX(); //where GetX() is any function that calculates the value of x
typedef std::conditional<x > 0, MyClass1,
std::conditional< x < 0, MyClass2,
MyClass3>::type>::type TheClass;
So that in the rest of the code I would only refer to TheClass, in such a way that it does not matter whether it is aliasing MyClass1, MyClass2 or MyClass3.
However, of course the code above does not work because when x has its value calculated from a function executed at the beginning of runtime, then std::conditional complains that x is not a constant. Which makes sense since typedef cannot be defined at runtime.
So, my question: is there a way to achieve what I am trying to do (not with typedef since I know it cannot be defined at runtime)? Remember that MyClass1, MyClass2 and MyClass3 are externally given by a library, and in such a way that I cannot easily alter them.
The only solution I can see is to use templates to generate the code for you. Modulo syntax errors, your std::conditional based solution does work provided you turn x into a compiler-known value. The trick is to wrap all of the code that uses the typedef in a template function/class that has the integer as a template parameter, as in:
template <int x>
void myMain(){
using TheClass = typename std::conditional<x == 0, MyClass1, MyClass2>::type;
Then you want to make sure that you compile all of the variants (0 and non-zero in my example) and to do so you explicitly call both myMain<0>() and, say, myMain<1>(), as in:
if(x == 0){
myMain<0>();
}
else{
myMain<1>();
}
Now you've turned the condition into something that's evaluated at run-time, but you have the code for both cases compiled and you can execute each (or both) of them to your heart content.
This has the drawback of making whatever uses the class into a template or something that is called by a template. Beyond the "dispatching" point, I would advise to be template on the type rather than on the integer (see the function doSomethingWithClass in the example); this better expresses the fact that your code can work with all of the types you're going to instantiate it with. If you want to make sure that you can only instantiate the functions with the three classes you are interested in, you should consider using the CRTP pattern (curiously recurring template parameter).
On the other hand, this has the advantage (with respect to the other answer based on polymorphism) that you can use the stack rather than the heap.
You can find a working example here.
Hope it helps.
To do this at compile time, the GetX function must be constexpr.
Using the comparison operators also conflicts with the template syntax. You will need to provide consexpr functions for less than and greater than:
constexpr int GetX(){ return 0;}
constexpr bool IsGreater(int x, int y) { return x > y;}
constexpr bool IsLess(int x, int y) { return x < y;}
typedef std::conditional<IsGreater(GetX(),0), MyClass1,
std::conditional<IsLess(GetX(),0), MyClass2,
MyClass3>::type>::type TheClass;
If you can't make GetX() constexpr (because the value is decided at runtime),
then you are looking for a Sum Type. They are quite common in functional programming languages and C++ now has library support in the form of std::variant.
Your example code could be turned into the following:
int main(){
//a type that can be 1 of 3 other types
std::variant<MyClass1,MyClass2,MyClass3> TheClass;
//decide what type it should be at runtime.
const int x = GetX();
if (x > 0) { TheClass = MyClass1(); }
else if (x < 0) { TheClass = MyClass2(); }
else { TheClass = MyClass3(); }
}
Here, you are deciding the type at runtime.
You can go on to use pattern matching for evaluating what type is held.
If all three inherit from a common class you can do this:
class BaseClass
{
virtual int GetSomething() = 0;
};
class Class1 : public BaseClass
{
virtual int GetSomething() override
{
return 1;
}
};
class Class2 : public BaseClass
{
virtual int GetSomething() override
{
return 2;
}
};
class TheClass : public BaseClass
{
virtual int GetSomething() override
{
return 3;
}
};
BaseClass* classInterface;
const int x = GetX(); //where GetX() is any function that calculates the value of x
if (x > 0) { classInterface = new MyClass1(); }
elseif (x < 0) { classInterface = new MyClass2(); }
else { classInterface = new TheClass(); }
printf(classInterface->GetSometing());
If not, you'll need to wrap them and do something like this:
class Class1
{
int GetSomething()
{
return 1;
}
};
class Class2
{
int GetSomething()
{
return 2;
}
};
class TheClass
{
int GetSomething()
{
return 3;
}
};
class BaseClass
{
virtual int GetSomething() = 0;
};
class Class1Wrapper : public BaseClass
{
Class1 m_class;
virtual int GetSomething() override
{
return m_class.GetSomething();
}
};
class Class2Wrapper : public BaseClass
{
Class2 m_class;
virtual int GetSomething() override
{
return m_class.GetSomething();
}
};
class TheClassWrapper : public BaseClass
{
TheClass m_class;
virtual int GetSomething() override
{
return m_class.GetSomething();
}
};
BaseClass* classInterface;
const int x = GetX(); //where GetX() is any function that calculates the value of x
if (x > 0) { classInterface = new MyClass1Wrapper(); }
elseif (x < 0) { classInterface = new MyClass2Wrapper(); }
else { classInterface = new TheClassWrapper(); }
printf(classInterface->GetSometing());
[Edit] ..if you want to save re-doing the if statements you could make a static method to generate a new baseclass:
static BaseClass* GetClass()
{
BaseClass* classInterface;
const int x = GetX(); //where GetX() is any function that calculates the value of x
if (x > 0) { classInterface = new MyClass1Wrapper(); }
elseif (x < 0) { classInterface = new MyClass2Wrapper; }
else { classInterface = new TheClassWrapper; }
return classInterface;
}
..then call it like this:
BaseClass* classInterface = GetClass();
// Do something
delete classInterface;
I would like to implement Object Orientated Programming in my lua interpreter, I understand that I can return a lua table from a C Function. And I would like the table that is returned to be full of C functions.
player = getClosestPlayer();
player.walkTo();
where both getClosestPlayer() and walkTo() are C functions.
From the C function for walkTo(), how do I differentiate between object types?
I would prefer every object to have a gid that I can use to identify it (player.gid) but how do I access that gid from the c function?
In other words, what is the equivalent of self.gid from C code?
int l_playerWalkTo(lua_State* functionState){
int gid = // self.gid?
// do something with gid
}
One way I could do this is to upvalue every single function in the table, but is there a more elegant way to do it?
Many thanks to macroland for his answer, I just though I would clear up what he has said.
This lua wrapper can be used to implement c++ classes into Lua:
https://bitbucket.org/alexames/luawrapper/overview
A great example of the usage of this library can be found here:
https://bitbucket.org/alexames/luawrapperexample/src/
Here is the code (taken straight from the example site)
Lua:
alicesaccount = BankAccount.new("Alice", 100)
alicesaccount:deposit(20);
alicesaccount:deposit(30);
alicesaccount:deposit(40);
c++:
BankAccount* BankAccount_new(lua_State *L)
{
const char* owner = luaL_checkstring(L, 1);
float balance = luaL_checknumber(L, 2);
return new BankAccount(owner, balance);
}
int BankAccount_deposit(lua_State *L)
{
BankAccount* account = luaW_check<BankAccount>(L, 1);
float amount = luaL_checknumber(L, 2);
account->deposit(amount);
return 0;
}
static luaL_Reg BankAccount_table[] =
{
{ NULL, NULL }
};
static luaL_Reg BankAccount_metatable[] =
{
{ "deposit", BankAccount_deposit },
{ NULL, NULL }
};
int luaopen_BankAccount(lua_State* L)
{
luaW_register<BankAccount>(L,
"BankAccount",
BankAccount_table,
BankAccount_metatable,
BankAccount_new // If your class has a default constructor you can omit this argument,
// LuaWrapper will generate a default allocator for you.
);
return 1;
}
As you can see, Using this method the first argument is an instance of the object
I had the similar problem and the way I resolved is:
1) Create an interface class in C++ with abstract methods
class LuaInterfaceOOP
{
public:
LuaInterfaceOOP(){}
virtual CObject* clone(void) const=0;
virtual wxString type(void)=0;
virtual wxString ToString(void)=0;
wxString GetType()return this->type();
wxString GetToString() return this->ToString();
virtual ~CObject(){}
};
2) Any class that you want to expose to Lua should implement this to be consistent.
class MyClass: public LuaInterfaceOOP
{
public:
wxString type() { return "MyClass";}
wxString ToString();
};
3) When you write a wrapper for this class make sure
int MyClass_toString(lua_State* L)
{
MyClass* mc= luaW_check<MyClass>(L, 1);
const char* str=mc->ToString().c_str();
lua_pushstring(L, str);
return 1;
}
int MyClass_type(lua_State* L)
{
lua_pushstring(L,"MyClass");
return 1;
}
4) Overload the type function provided by Lua, for you the important part will be:
case LUA_TUSERDATA:
{
wxString str1;
if(lua_getmetatable(L,idx)) // Stk: Userdata Table
{
lua_getfield(L,-1,"type"); // Stk: Userdata Table function
if(!lua_pcall(L,0,1,0)) // Stk: Userdata Table string
{
str1<<lua_tostring(L,-1);
wxReturnStr<<str1;
lua_pop(L,2);// Stk: Userdata
}
else //stk: Userdata table
{
lua_pop(L,1);
wxReturnStr<<"userdata"; //stk: Userdata
}
}else wxReturnStr<<"userdata";
break;
}
EDIT 1: Adding code to wrap C++ funcs to Lua
static luaL_Reg MyClass_table[] = {
{ NULL, NULL }
};
static luaL_Reg Myclass_metatable[] = {
{"type", Myclass_type},
{"__tostring", Myclass_toString},
{ NULL, NULL }
};
Finally,
static int luaopen_MyClass(lua_State* L)
{
luaW_register<MyClass>(L, "MyClass", MyClass_table, MyClass_metatable, MyClass_new);
return 1;
}
Now in Lua you can use an expression such as if(type(aclass)=="MyClass")
I am not sure if these steps are the best way, but so far it worked.
You're given two structs. One of type 'A', another of type 'B'.
The one of type 'B' has a struct of type 'A' in it. So something like this:
struct A {
void print_stuff(A * a){ puts("From A"); }
};
struct B {
A a_part;
char * s;
void print_stuff(B * b){
printf("From B\n\t%s\n", b->s);
}
};
B * B_new(char * str) {
B * b = (B*)malloc(sizeof(struct B));
b->s = strdup(str);
return b;
}
You want to be able to call struct B's 'print_stuff' function, even with code like this:
A * aptr = (A*) B_new("foo");
aptr->print_stuff(aptr);
You are NOT allowed to use inheritance, C++ containers or classes. Struct B MUST have a_part.
How would you write your code so that regardless of the type of the pointer, the correct print_stuff function is called (in this case, if a pointer to a struct of type B was casted to A*, how would you guarantee that the print_stuff function in B is called)?
You could make print_stuff a function pointer, but then you need to manually hook it up to the correct function. In this case though, you're just replicating C++ inheritance mechanisms so it's pointless.
The A object can't automatically know where it's contained, or if it's contained at all.
So the bottom line is, just use C++ inheritance.
This is really horrible. But yes, there is a way to do it. Put a bool field in A, and in the same place in B, to indicate the real type. The code below should give you an appreciation of C++ (and really shouldn't be used for any other purpose).
struct A {
bool isB;
A()
{
isB=false;
}
void print_stuff(A * a);
};
struct B {
bool trueB;
A a_part;
char * s;
B()
{
isB=true;
}
void print_stuff(B * b){
printf("From B\n\t%s\n", b->s);
}
};
void A::print_stuff(A * a)
{
if(isB)
{
B* b = (B*)(this);
b->print_stuff(b);
}
else
puts("From A");
}
B * B_new(char * str) {
B * b = (B*)malloc(sizeof(struct B));
b->s = strdup(str);
b->trueB=true;
return b;
}