I have a child class that is derived from a parent class. I need to use conditional logic to figure out which arguments to pass to the parent class constructor. I am doing this as follows:
Child::Child(const std::string & foo)
:Parent(foo=="x"?someClassPtr(new someClass()):someClassPtr(new someOtherClass()))
{
}
But what if I want to pass a different argument for foo=="y" and foo=="z"? Is there some way to do this without using the ternary operator?
Although you can definitely do it with nested conditional expressions, I would recommend against it: the expression borders on non-readable even with a single conditional, let alone two or three nested ones.
Using a private static member function would be a good choice for this task: the function could "parse" the value of foo, and decide on the proper object to return:
Child::Child(const std::string & foo)
: Parent(constructParentArgs(foo)) {
}
private static someClassPtr *constructParentArgs(const std::string& foo) {
if (foo == "x") return someClassPtr(new someClass());
if (foo == "y") return someClassPtr(new someOtherClass());
if (foo == "z") return someSubClassPtr(new yetAnotherClass());
// provide a default value here
return someClassPtr(new defaultClass());
}
The advantage of this approach for the readers of your code is that they do not have to bother themselves with the details of calling the parent constructor, unless they want to see what is going on. When they read the header, all they know that your code somehow creates parent argument. If they want to learn how exactly the argument gets constructed, they can always go straight to the private member function.
Related
If I want to call function foo on an object thisThing (in C# jargon, this is called the "receiver", so I'll call it that here too) and pass the argument myStuff, I'll do it like this:
thisThing.foo(myStuff);
Super simple, nothing surprising going on here.
If I want to change the argument to yourStuff if a bool value b is false, I'll do it like this:
thisThing.foo(b ? myStuff : yourStuff);
Also very simple, basic use of the ternary operator.
If I want to change the receiver to otherThing if b is false, I'll do it like this:
(b ? thisThing : otherThing).foo(myStuff);
A little bit weirder, you probably don't do this super often, but it's nothing crazy either.
But if I want to change the called function to bar if b is false, how do I do that?
I would think something like this:
thisThing.(b ? foo : bar)(myStuff);
But of course, this does not work.
Is there a simple, neat-looking, performant way of doing this, preferrably without redundantly specifying anything?
There will probably have to be some compromises made, but the point is to not have to repeat the receiver and arguments. So the following works:
if (b)
{
thisThing.foo(myStuff);
}
else
{
thisThing.bar(myStuff);
}
But you have to repeat the receiver and arguments. Imagine that thisThing and myStuff are placeholders for much more complex expressions. You might want to put those in local variables first, but that has implications for copying, and it does not play nicely if you have many arguments.
You might be able to take function pointers to those member functions and then do something like (b ? pointerToFoo : pointerToBar)(myStuff);, but dealing with function pointers tends to be messy (think function overloading) and it does not seem like something that the compiler would properly optimize away. But I'd be happy to be proven wrong here.
You can use member function pointers, but you need special syntax to call the function via the pointer:
struct X {
void foo() {}
void bar() {}
};
int main() {
X thisThing;
bool b = false;
(thisThing.*(b ? &X::foo : &X::bar))();
}
However, I would not recommend to actually use it like this (unless there are reasons not shown in the question). Note that it won't work like this when foo or bar are overloaded.
Anyhow, in my opinion also your other examples are not good use-cases for the conditional operator. The conditional operator is not just a equivalent replacement for if-else. It has slightly different use-cases. Sometimes one uses the conditional operator to determine the common type of two expressions. Sometimes you cannot use an if-else. For example when initializing a reference:
int& x = a ? c : d; // cannot be done with if/else
My advice is: Don't use the conditional operator to save on typing compared to an if-else. The difference between if-else and the conditional operator is almost never the amount of code you have to write only.
What about:
thisThing.foo_or_bar(b, myStuff);
and:
ThingClass::foo_or_bar(bool b, SomeType myStuff)
{
if (b)
foo(myStuff);
else
bar(myStuff);
}
Similar to #463035818_is_not_a_number's answer, but rather than using the pointer to member operator(.*) and all the parentheses, I would use std::invoke instead:
struct X {
void foo() {}
void bar() {}
};
int main() {
X thisThing;
bool b = false;
std::invoke(b ? &X::foo : &X::bar, thisThing);
}
However, just like the original answer, this cannot be used if function overloads were included.
I'm having a class that contains a function pointer. I would like to initialize various instances of the class statically but I can't figure out the correct syntax for this.
Let's say, this is my class
class fooClass
{
int theToken;
string theOutput;
bool (*theDefault)( void );
};
I now would like to create a static instance of this, like this…
fooClass test
{
1,
"Welcome",
(){ return (theToken & 1 ) ? true : false; }
};
As I said, I can't figure out the proper syntax for the function pointer line. Or is it even possible like this? I'd really like not having to break out every function I create this way into its own function declaration.
What I'm trying to do is, allow each instance to have a unique default function because each instance represents a unique data-driven building block of a bigger system. The code I put in there is just for illustrative purposes. This default function will access certain global variables as well as some of the member variables and if need be I could pass this into the function.
Could someone point me in the right direction how I'd have to write the initialization for it to work under C++14?
If you want to refer to struct members inside the function, you cannot do with just a plain function pointer not receiving any argument, as it doesn't receive the this pointer.
My advice is to at very least change it to a pointer to a function taking the instance as an argument, then in initialization you can pass a capture-less lambda (which can be converted to a plain function pointer):
class fooClass
{
int theToken;
string theOutput;
bool (*theDefault)( fooClass *that);
// you may provide a helper for ease of use
bool Default() { return theDefault(this);}
};
fooClass test
{
1,
"Welcome",
[] (fooClass *that){ return (that->theToken & 1 ) ? true : false; }
};
You can also use an std::function<bool(fooClass*)> to allow even functors, lambdas with captures & co. if you are ok with the increased overhead.
You may be tempted to use a plain std::function<bool()> instead, and use a lambda capturing the instance by reference, such as
fooClass test
{
1,
"Welcome",
[&test] (){ return (test->theToken & 1 ) ? true : false; }
};
This does work, but is extremely dangerous if test happens to be copied, as theDefault will still refer to test even in the copy (and even after the original will have been destroyed).
(incidentally, this is how OOP is often done in languages such as Lua, but there (1) objects are not copied and (2) automatic memory management makes sure that closures "keep alive" the objects they capture)
I'm a Java developer trying to pick up C++. Is it okay to use a setter inside a constructor in order to reuse the sanity checks the setter provides?
For example:
#include <stdexcept>
using namespace std;
class Test {
private:
int foo;
void setFoo(int foo) {
if (foo < 42) {
throw invalid_argument{"Foo < 42."};
}
this->foo = foo;
}
public:
Test(int foo) {
setFoo(foo);
};
};
Yes, it is recommended to do this, basically for the reason you already mentioned.
On the other hand you should ask yourself if you need the setter at all and not directly implement the checks inside the constructor. The reason I am writing this is that setters in general result in mutable state which has many disadvantages as opposed to immutable classes. However sometimes they are required.
Another recommendation: If your class variable is an object and you can modify the constructor of this object, you could put the check into the constructor of this object:
class MyFoo {
public:
MyFoo(int value) {
if (value < 42) {
throw invalid_argument{"Foo < 42."};
}
v = value;
}
private:
int v;
}
This will enable you to use an initialization list in the constructor of your Test class:
Test(int foo) : foo(foo) {}
However, now the check is a property of the class of the variable and no longer one of the owning class.
Yes you can. It's fine as long as your setters are not virtual, because it's inheritance hierarchy in calling right functions as the "this" ptr is not ready yet.
Here is Herb Sutter GOTW on this matter: http://www.gotw.ca/gotw/066.htm
Yes, that's fine as long as it makes sense to have a setter for a particular member variable (have some logic that can't be checked by assignment only for example) . In this example, setFoo could've just taken an unsigned int and the caller would know not to pass negative values. Which in turn could eliminate the check and thus the need for a setter. For more elaborate checks, a setter and usage of that setter in the constructor is just fine.
Short answer: Yes. In fact, your example works.
Long answer: But it is not a good practice. Al least, you have to take care.
In general, a set function works with a constructed object. It is supposed that the invariant of the class holds. The functions in a class are implemented considering the invariant is true.
If you want other functions to be used in a constructor, you would have to write some code. For example, to create an empty object.
For example, if in your class you change setFoo in the future (let's say setFoo changes the member foo only it is larger) you example stop working.
This is okay.
The only situation you cannot call member function is when the base classes are not constructed yet.
can member functions be used to initialize member variables in an initialization list?
I know this doesn't fit your situation. Its just for the sake of completeness:
When you are simply settings member values (without checks like yours in setFoo) it is recommended to use initialization lists in the constructor. This prevents members being "initialized" 2 times: 1. with their default value, 2. with the value that you passed into the constructor.
class Test {
private:
int foo_;
public:
Test(int foo)
: foo_(foo)
{ };
};
I came across the following code in a project.
map_erase_if(cfgIp.m_raw, RawCreate());
I understand that this will call the function defined by () inside the structure.
The Rawcreate is a structure which is given below .
struct RawCreate {
bool operator()(const Device::StoreElm& el) {
Pcap* pcap = NULL;
pcap = Pcap::findServer(el.second->name());
if (!pcap) {
try {
MEM_NEW(pcap,Pcap(*el.second));
} catch (Exception& ex) {
MAND_LOG(DBG_SIPTCP, "Error:%s", ex.what());
}
}
for (RejItr itr = CfgIp::m_rejectList.begin(); itr != CfgIp::m_rejectList.end(); ++itr) {
if(ip_equal(itr->first, pcap->getInterface(), false) && !itr->second.empty()) {
pcap->blockReg();
}
}
if (pcap) {
MEM_DELETE(el.second);
return true;
}
return false;
}
};
I have seen operator overloading with class objects.I know class and structure has only few differences in cpp.But using overloading within a structure in this way is a new thing for me.Can any one clarify its usage?
RawCreate()
I understand that this will call the function defined by () inside the structure.
If RawCreate is a function, then this will call it. If it is a type, then it will construct an instance. RawCreate is a class, so the latter is true. T::operator() is not called by this expression.. unless RawCreate is a variable of type T that defines the operator.
I know class and structure has only few differences in cpp
Just to clarify, the only difference is that classes declared with the struct keyword and those declared with class keyword have a different access specifier by default.
Can any one clarify its usage?
The documentation of map_erase_if should describe how the operator is used. Presumably, the operator() of the functor is used as a predicate for erase.
RawCreate() creates an instance of RawCreate.
Your code works like this code:
RawCreate c;
map_erase_if(cfgIp.m_raw, c);
but avoids creating an unnecessary variable.
Presumably, map_erase_if is then going to call the instance's operator() with each member of cfgIp.m_raw (or pass the instance on to something that does).
As the others said, RawCreate() does not call the operator (), it just creates an instance (which is then copied over).
The operator () is then (most likely) called for each item of the map when iterating during map_erase_if() (and if the operator returns true, the item will be erased, if the function works as the name advertises).
I am currently trying to make sure that a member function of one class is only called by a member function of another class.
The architecture is imposed and cannot be changed, the port means that some logic has to be done in a.call() before calling b.call(). a.call() therefore calls b.call() to simplify things and make sure the order is respected.
I found this answer to my question. Only, the problem is that I am using classes, and the two classes have the same member function name and so the #define tries to replace all the occurrences which have different prototypes.
I recommend the passkey pattern. It's very good for giving fine grained control on who can do what with your function.
Off the top of my head, options would be:
Make b.call private and make b add a or a.call as a friend
Turn b.call into a class and put the body into a a private constructor with a or a.call as a friend
grep the source code for b.call, make sure the only call is in a.call, and add a comment at the declaration saying "if you call this function you will be fired"
Change b.call to take at least one of the values it needs as a parameter (even if it ignores it and uses the value from somewhere else)
Can you change b.call to take a reference to a? This way, b.call can call a.call itself:
struct A {
void call() {
// do stuff
}
};
struct B {
void call(A & a) {
a.call();
// do stuff
}
};
This makes sure that a.call is always called before the rest of b.call is executed.
How about using a flag?
a.call()
{
// ...
flag = 1;
b.call();
flag = 0;
}
b.call()
{
if (flag == 0)
return;
// ...
}
If you program for certain platform (say x86 or x64), and you know the calling convention (e.g. cdecl), then you can get this info from the stack
Say you want to check the object that called the function, so use the this pointer that is pushed to the stack prior to calling the member function: get the this pointer and compare it with the object that you want (this_pointer == a)
If you want to check certain function, get the caller address from the stack and check against that function: caller_address == A::call. If it's a virtual function, use the this pointer to get the vtable.
Depending on the calling-convention and the order of pushing variables on the stack, you may have to check first the input variables sizes, in order to get to the information you need.