When creating a function for a class, should the parameter take a pointer to the class type and be invoked using 'this', or create a parameterless function and call it normally. Here is a demonstration:
class ExampleOne {
ExampleOne::ExampleOne() {
performAction(this);
}
void ExampleOne::performAction(ExampleOne *obj)
{
// Do something
}
}
class ExampleTwo {
ExampleTwo::ExampleTwo() {
performAction();
}
void ExampleTwo::performAction()
{
// Do something
}
}
In ExampleOne, the class functions are called with a pointer reference to itself. In ExampleTwo, functions are called without parameters.
I have seen both methods used in c++ code, and do not know which is the correct programming method.
The same question applies to working with the global instance variables, like this:
class ExampleThree {
ExampleThree::ExampleThree() {
Object *obj = new Object;
someFunction(obj);
}
ExampleThree::someFunction(Object *obj) {
// Do something
}
}
Or do we work with the instance variables rather than pointers to it:
class ExampleFour {
ExampleFour::ExampleFour() {
Object *obj = new Object;
someFunction();
}
ExampleFour::someFunction() {
// Do something with Obj instance
}
}
The reason this is done is code reuse, when some work done in the constructor can be used in other functions, if it can't then you should not make a separate function. And you shouldn't make the reuse function before there is a need.
The C++03 way
A {
A() {
Common(42);
}
A(int a) {
Common(a);
}
void Common(int c) {
... do something really complicated with c
}
}
The C++11 way
A {
A() : A(42) { // you can now call other constructors.
}
A(int a) {
... do something really complicated with c
}
}
Also in C++11 the move constructor and move assignment function mostly shares the same code (the latter has a return also) which could be reused.
The preferred way is to do everything in the initializer list for the constructor, which makes everything more safe. And only do something in the body if really needed.
C {
int dc;
C(int c) : dc(c) {
}
}
When you write something like this
MyClass myObject;
myObject.someFunction();
myObject is implicitly passed by reference to MyClass::someFunction, so you can access its attributes or methods by their names, without using the keyword this.
The usual way to use this is when you actually need a pointer or a reference to your object. For example, it is common when you overload operator=() to make it return a reference to the object with return *this;
Related
I've read several topics about that kind of problem - but can't find a simple and good solution. Here is the code:
void SomeFunction() { }
class A {
public:
typedef std::function<void(void)> AFunction;
static void AMethod(AFunction f) { f(); }
};
class B {
public:
void B1Method() { }
void BCorrectCall() { A::AMethod(SomeFunction); }
void BIncorrectCall() { A::AMethod(B1Method); }
};
Problem is here void BIncorrectCall() { A::AMethod(B1Method); }, where I receive error about invalid casting. What is the simplest way to achieve that kind of behaviour? Thanks a lot for any advice!
Use a lambda:
A::AMethod([this]{B1Method();});
It doesn't matter in this case, but if you wanted to store AFunction f and use it after the call to AMethod, you'd have to ensure that the B instance (the address of which is saved in the lambda) says alive as long as you use the function.
C++17 allows you to capture *this instead, which will copy the entire B instance into lambda, but normally it's not what you want.
You could do something similar with std::bind (see the other answer), but lambdas are more flexible.
B1Method is not void(*)(void), it's void(B1::*)(void).
You may do
void BIncorrectCall() { A::AMethod(std::bind(&B1::B1Method, this)); }
};
The issue is that B::B1Method() is a non-static member function in B and, therefore, it needs to be called on an instance of B.
If the implementation of B1Method() doesn't use any non-static data member of B and it doesn't call any other non-static member function of B, then simply declaring it as static will work with your current implementation of BIncorrectCall() as you will no longer need to call B1Method() on an instance of B:
class B {
public:
static void B1Method() { } // static now
void BCorrectCall() { A::AMethod(SomeFunction); }
void BIncorrectCall() { A::AMethod(B1Method); } // no change
};
Otherwise, you have to keep an object of type B whenever you want to call B1::B1Method().
The easiest way is to make it static and so there is no this object, but if you need it (the this object), you can use lambdas:
class B {
public:
void B1Method() { }
void BCorrectCall() { A::AMethod(SomeFunction); }
void BIncorrectCall() {
std::function<void(void)> el = [&](){this->B1Method();};
A::AMethod(el);
}
};
The problem is that 'B1Method' is not a simple function - it's a class method. That means that when you call myB.B1Method(), you're actually calling 'B1Method(&myB)', effectively passing the this pointer as a hidden argument - so you can't convert M1Method to a std::function without specifying which object it should act on.
One approach that should work is using std::bind to construct a callable object from a combination of an object (class instance) and the method. Something like:
void BNowCorrectCall() { A::AMethod(std::bind(&B::B1Method, this)); }
I have some overloaed methods which take some different pointer types.
Now I want to call one specific method with nullptr as a parameter.
I know that I could cast the nullptr to the specific type of pointer, the method I want it to call takes.
But I don't want to/can't cast the nullptr.
This example shoud explain what I am trying to do:
class Foo {
//some attributes
};
class Bar {
//some attributes
};
void myMethod (Foo*) {
//I want this method to be called
}
void myMethod (Bar*) {
//Not this one
}
int main () {
myMethod(nullptr); //Something like this
// myMethod(static_cast<nullptr>); //I don't want to write this.
return 0;
}
If I just call it with the nullptr I get
error: call of overloaded 'myMethod(std::nullptr_t)' is ambiguous
because the compiler doesn't know which of the methods it should call.
Is there a way to do what I want?
Like something similar to the template specialization?
You can create an overload which take std::nullptr_t as argument, and then in it call the exact function wanted (through casting):
void myMethod(std::nullptr_t)
{
myMethod(static_cast<Foo*>(nullptr));
}
You can create pointer of Foo and Bar and let both point to nullptr. Now you can call a overloaded function by passing pointer variable as argument.
class Foo {
//some attributes
};
class Bar {
//some attributes
};
void myMethod (Foo*) {
//I want this method to be called
}
void myMethod (Bar*) {
//Not this one
}
int main () {
Foo* foo=nullptr;
Bar* bar=nullptr;
myMethod(foo); //This will call myMethod(Foo*)
return 0;
}
Some programmer dude has a good suggestion, but you could also add a default parameter to one of your methods if you were happy to call it without passing nullptr, like so:
void myMethod (Foo* = nullptr) {}
void myMethod (Bar*) {}
int main () {
myMethod();
}
Like something similar to the template specialization?
If that means that you wish to specify the target class on a case by case basis, you can turn the overload in #Some programmer dude's answer into a template.
template<class C>
void myMethod(std::nullptr_t) {
myMethod(static_cast<C*>(nullptr));
}
Now you can use a simple template name to call the overload you want
myMethod<Foo>(nullptr); // What you want now.
myMethod<Bar>(nullptr); // What you may want at another point.
myMethod<Baz>(nullptr); // What you may want sometime in the future,
// after adding another overload.
Coming from the Java/PHP world, I am still new to C++. Some simple things to do in other languages are a bit trickier to do in C++.
My main issue is the following. Right now, I have a class (ie. "Something") for which the constructor is injected with a virtual class dependency (ie. a children of "Base"). Then, the constructor stores this injected instance in a unique_ptr<Base> class field (using the clone idiom). This works well at the application level, everything seems to works as expected. Here is the sample code:
class Base {
public:
virtual std::unique_ptr<Base> clone() = 0;
virtual void sayHello() const = 0;
};
class Something {
public:
explicit Something(Base &base) { this->base = base.clone(); }
void sayHello() const { base->sayHello(); }
private:
std::unique_ptr<Base> base;
};
But to make sure it does, I wrote unit tests to test its behavior. In those tests, I want to assert the injected dependencies methods are actually called. So logically, injecting a "spy" dependency should do the trick.
Here is what I did at first:
class SpyDerived : public Base {
public:
explicit SpyDerived() = default;
SpyDerived(const SpyDerived &original) { this->someState = original.someState; }
std::unique_ptr<Base> clone() override { return std::make_unique<SpyDerived>(*this); }
void sayHello() const override { std::cout << "My state: " << someState << std::endl; }
void setSomeState(bool value) { this->someState = value; }
private:
bool someState = false;
};
This is the main function I use to this this out:
int main() {
SpyDerived derived;
Something something(derived);
derived.setSomeState(true);
something.sayHello();
}
For obvious reasons, someState value on print is always false. I get that the Derived instances in Something is a new copy of Derived and no longer the one that was created in the main function.
So basically, what I am trying to achieve here is to have the Something class always use the SpyDerived instance created in the main function. Is there any way I could make this work. I am trying to avoid changing the design just for test purposes.
I am using MSVC 2015 to compile the code. Keep in mind that smart pointers, C++ idioms, copy/move constructors are fairly new concepts for me.
Thanks for your help.
Well, do you want to clone your instance, or simply reference that instance?
The clone idiom is made to copy the instance of a class, making the new instance independent of the old instance.
You are basically making this, in term of PHP:
<?php
interface Base {
public function sayHello();
}
class SpyDerived implements Base {
private $someState = false;
public function sayHello() {
echo 'My state: ' . $this->someState;
}
}
class Something {
public __construct(Base $base) { $this->base = clone $base; }
public function sayHello() { $this->base->sayHello(); }
private $base = null;
}
$derived = new SpyDerived;
$something = new Something($derived);
$derived->setSomeState(true);
$something->sayHello();
?>
You see this? $base is cloned. Something::$base is a copy.
So in PHP, what would you do to solve that problem?
Simple! Remove that clone, no copies!
Well, in C++, this is the same thing. If you have an object pointer and don't want to clone it, don't actually call the clone method.
We will change your class to, like PHP, contain a reference to the object. We will start by making Something contain a non owning reference:
class Something {
public:
explicit Something(Base& b) : base{b} { }
void sayHello() const { base.sayHello(); }
private:
// we simply contain a reference to the base
Base& base;
};
In C++, a reference does not own the object. If the object is destroyed, all reference pointing to that object will point to a dead object.
As you can notice, your tests stays the same and work:
int main() {
SpyDerived derived;
Something something(derived);
derived.setSomeState(true);
something.sayHello();
}
If you want Something be the owner of Base, then use std::unique_ptr<Base>:
class Something {
public:
explicit Something(std::unique_ptr<Base> b) : base{std::move(b)} { }
void sayHello() const { base->sayHello(); }
private:
std::unique_ptr<Base> base;
};
Beware that the ownership of base should be transferred from the caller to the something class. That transfer is express through that std::move thing, because we are moving the ownership of that resource.
Then in your tests:
int main() {
auto derived = std::make_unique<SpyDerived>();
// We want to keep a non-owning reference of derived
// The star (*) operator of std::unique_ptr returns a reference to the pointed object
auto& derived_ref = *derived;
// We transfer the ownership of derived to the `Something`
Something something(std::move(derived));
// Since derived is a reference to the object pointed by our pointer,
// It will affect the value we found in `Something`, because they are
// both pointing to the same instance.
derived.setSomeState(true);
something.sayHello();
}
Since Something is owner of derived, the non-owning reference derived_ref will point to a dead object if something dies before.
I need a class like that:
class MyClass
{
MyClass()
{
}
public:
MyClass(signed = 0)
{
}
}
I'm wondering if it's possible to call these constructors selectively. Actually what I need is to have two versions of constructors. One to create object with default value like second constructor in my example and the other one to create a default/raw/uninitialized object without any parameters which is used internally in the same class.
I can do following to get over this problem:
class MyClass
{
MyClass(float)
{
}
public:
MyClass(signed = 0)
{
}
}
And to call the first constructor inside my class but it's weird to have unused parameter.
You have a few options. Your "work-around" isn't crazy, and in fact it's a pattern that is encouraged in some circumstances. But consider the named-constructor idiom instead: If you need to create an uninitialized object in a member function of the same class, then create a named private c'tor that achieves this for you:
class MyClass {
public:
MyClass(float f = 0.) : value_{f} {}
private:
float value_;
void g();
MyClass invalid()
{
return MyClass{std::numeric_limits<float>::max()}; }
};
That way, inside of MyClass::g(), you can do:
void MyClass::g()
{
auto newObj = invalid(); // call named c'tor
newObj.value_ = 3.14159;
std::swap(newObj, *this) // swap current object with 'newObj'
// or whatever.
}
I have some code like that:
#include <string>
class another_foo
{
public:
another_foo(std::string str)
{
// something
}
private:
// something
};
class foo
{
public:
foo();
private:
another_foo obj;
};
foo::foo() : obj(str) // no `: obj("abcde")`, because it is not that simple in real situation.
{
std::string str = "abcde"; // generate a string using some method. Not that simple in real situation.
// do something
}
and I am going to initialize obj which is a private member of foo. But this code does not compile. How can I use the variable in the constructor's body in the initialization list?
AFAIK, the only method is to separate the code generating str from the constructor as another function, and then call that function directly in the initialization list. That is...
#include <string>
class another_foo
{
public:
another_foo(std::string str)
{
// something
}
private:
// something
};
class foo
{
public:
foo();
private:
another_foo obj;
// std::string generate_str() // add this
static std::string generate_str() // EDIT: add `static` to avoid using an invalid member
{
return "abcde"; // generate a string using some method. Not that simple in real situation.
}
};
foo::foo() : obj(generate_str()) // Change here
{
// do something
}
But is there any better method?
Yes, you have to move it to a function. If it's a single-purpose thing (only used for this initialisation) and you have access to C++11 lambdas, you can use a single-purpose lambda. Otherwise, just use a member function like you did. Just be careful about calling virtual functions in there, because the object is still under construction. Best make it static, if possible.
Lambda example:
class foo
{
public:
foo();
private:
another_foo obj;
};
foo::foo() : obj([] { return "abcde"; } ())
{
// do something
}
But is there any better method?
To be short: No, not if you're not willing to change either the way obj is allocated OR it's semantic.
You can do variants of this, like making generate_str() static, or better (if the code is short) using a lambda:
foo::foo() : obj( []{ return "abcde"; }() )
{
}
HOWEVER: If the object construction requires logic which is dependent on other members, then you have to make sure the initialization order of members reflect the inter-dependencies (order them in the declaration from the independant to the dependants) OR BETTER: change the semantic of obj OR allocate it on the heap.
Changing allocation have a cost on construction/destruction and a very minor cost on access, so it's not the best solution most of the time, but it solves the problem:
class foo
{
public:
foo();
private:
std::unique_ptr<another_foo> obj; // no sharing of the instance
};
foo::foo() // obj is null
{
// do something
auto result_obj_info = compute_something();
obj = new another_foo( result_obj_info );
// OR if you use this http://stackoverflow.com/questions/12547983/is-there-a-way-to-write-make-unique-in-vs2012
obj = std::make_unique<another_foo>( result_obj_info );
}
However, I would recommand changing the semantic of another_foo instead so that it have value semantic:
#include <string>
class another_foo
{
public:
another_foo(); // this create an invalid anoter_foo, unusable.
another_foo(std::string str) // this create a valid another_foo
{
// something
}
// make sure copy/move functions are available, either automatically or manually
bool is_valid() const;
private:
// something
};
inline bool is_valid( const another_foo& obj ) { return obj.is_valid(); }
class foo
{
public:
foo();
private:
another_foo obj;
};
foo::foo()
{
assert( is_valid( obj ) == false);
std::string str = "abcde"; // generate a string using some method. Not just simple like that in real situation.
// do something
obj = another_foo( str );
assert( is_valid( obj ) == true);
}
That way your another_foo type acts like a handle for it's resources. If it shouldn't be copied, just make it move-only. Take a look at how std::thread or std::unique_ptr work for example.
The risk when writing a member function that will be called during construction is that you may change it afterwards to use some of the class' data members, which may not have been initialized at the time of the call.
It's probably better to define an external function to generate the string, like this:
namespace {
std::string generate_str()
{
return "abcde";
}
}
foo::foo() : obj(generate_str())
{
// do something
}
That way, if you have to pass parameters to the function, the use of uninitialized data members or virtual member function return values will be visible from the constructor, hence more easy to catch.
If it's a constant specific to that class, you can define it that way:
class foo {
public:
foo();
private:
static const std::string STR;
another_foo obj;
};
const std::string foo::STR = "abcde";
foo::foo() : obj(STR)
{
}
Edit
Since it seems it's not a constant, you may have to use a static member function for this job. (Or a lambda, your choice)
class foo {
static std::string generate_string() const;
};
Implementation:
std::string foo::generate_string() const {
return std::string("abcde");
}