class foo{
public:
bar steal_the_moveable_object();
private:
bar moveable_object;
};
main(){
foo f;
auto moved_object= f.steal_the_moveable_object();
}
How can implement steal_the_movebale_object to move the moveable_object into the moved_object ?
You can simply move the member directly in the return statement :
class foo
{
public:
bar steal_the_moveable_object()
{
return std::move(moveable_object);
}
private:
bar moveable_object;
};
Beware that this may not be a good idea though. Consider using the following instead so that the method can only called on R-Values :
class foo
{
public:
bar steal_the_moveable_object() && // add '&&' here
{
return std::move(moveable_object);
}
private:
bar moveable_object;
};
int main()
{
foo f;
//auto x = f.steal_the_moveable_object(); // Compiler error
auto y = std::move(f).steal_the_moveable_object();
return 0;
}
Related
I was going through a book called Programming Principles and Practices using C++ but found a strange behavior of class construction.
Suppose I have a class as follows:
class Foo {
public:
Foo(int x)
: y { x } { }
private:
int y;
};
and I have another class which has an instance of class Foo as its member object
class Bar {
public:
Bar(Foo x)
: y { x } { }
private:
Foo y;
};
When I do the following:
int main()
{
Bar obj_1 { Foo { 1 } };
Bar obj_2 { 2021 }; // this doesn't give me error?
return 0;
}
obj_1 was constructed as specified in the constructor, but obj_2 doesn't give me any error message and to me it seems it just magically works.
My intention of having a member of a class as an instance of another class was to force the constructor to take a class instance as its argument, but not an integer.
Why doesn't it give me incorrect type error?
You can prevent this implicit conversion by declaring the Foo constructor explicit
explicit Foo(int x) : y { x } { }
in main this would require the caller to change their obj_2 instantiation to
Bar obj_2 { Foo{2021} };
I want to pass function of one object to another function as an argument. Below code is only for indication of the problem, (not realistic code). How can function IdNeeded can take function getNextId of class Bar?
class Foo
{
public:
void IdNeeded(getNextId);
}
class Bar
{
public:
int getNextId()
{
return ++id;
}
private:
int id = 0;
}
int main()
{
Bar bar;
Foo foo;
foo.IdNeeded(bar.getNextId); // foo will get id = 1
Foo anotherFoo;
anotherFoo.IdNeeded(bar.getNextId); // anotherFoo will get id = 2, because "id" is already incremented by one for foo object
}
I tried to use std::function, function pointer, std::bind, but unfortunately could not reach a final solution.
Provide a proper call back definition, and use a lambda to pack your object Foo:
#include <functional>
class Foo
{
public:
void IdNeeded(std::function<int()> f){ f();}
};
class Bar
{
public:
int getNextId()
{
return ++id;
}
private:
int id = 0;
};
int main()
{
Bar bar;
Foo foo;
foo.IdNeeded([&](){return bar.getNextId();}); // foo will get id = 1
}
In C++, is there any way to have something like a temporary variable in an initialization list. I want to initialize two constant members with the same instance of something without having to pass that something in, remove the const requirement, use a Factory (i.e. pass it in but have the factory generate it to hide it from the API user), or have temp actually be a member variable.
I.e. something like
Class Baz{
const Foo f;
const Bar b;
Baz(Paramaters p):temp(p),f(p,temp),b(p,temp){ //temp is an instance of Something
// But NOT A member of Baz
// Whatever
}
}
instead of
Class Baz{
Foo f;
Bar b;
Baz(Paramaters p){
Something temp(p);
f = Foo(p,temp)
b = Bar(p,temp)
}
}
or
Class Baz{
Foo f;
Bar b;
Baz(Paramaters p,Something s):f(p,s),b(p,s){
}
}
In C++11 you could use delegating constructors:
class Baz{
const Foo f;
const Bar b;
Baz(Paramaters p) : Baz(p, temp(p)) { } // Delegates to a private constructor
// that also accepts a Something
private:
Baz(Paramaters p, Something const& temp): f(p,temp), b(p,temp) {
// Whatever
}
};
There's a couple of patterns to achieve this.
In C++11 use delegating constructors:
class Baz {
public:
Baz(Paramaters p) :
Baz{p, Something{p}}
{}
private:
Baz(Paramaters p, Something temp) :
f{p, temp},
b{p,temp}
{}
const Foo f;
const Bar b;
};
Use a base class:
class BazBase {
public:
BazBase(Paramaters p, Something temp) :
f{p, temp},
b{p,temp}
{}
protected:
const Foo f;
const Bar b;
};
class Baz : private BazBase {
public:
Baz(Paramaters p) :
BazBase{p, Something{p}}
{}
};
Use a factory method:
class Baz {
public:
static Baz make(Parameters p)
{
return {p, Something{p}};
}
private:
Baz(Paramaters p, Something temp) :
f{p, temp},
b{p,temp}
{}
const Foo f;
const Bar b;
};
my question is as follows: Suppose I have:
class Foo
{
public:
Foo() {}
void setInt(int i) { myInt = i; }
int getInt() { return myInt; }
private:
int myInt;
};
class Bar
{
public:
Bar(Foo f) { /* do something with f.getInt() */ }
};
Now I have another class that has Bar as a member vairable:
class BarUser
{
public:
BarUser();
private:
Bar bar;
};
I want to write BarUser's constructor, however I want to initialize Bar with a Foo member that has 3 as its integer. I.e.:
Foo f;
f.setInt(3);
Bar b(f);
However since I have Bar as a class member, I cannot write all this code in the initialization list... What I mean is:
BarUser::BarUser() : bar(/* Foo after executing f.setInt(3) */)
{ ... }
Suppose assignment operator is not allowed for Bar - how can I initialize it as intended?
Thanks!
If you can't change Foo, write a function:
Foo make_foo(int i) {
Foo f;
f.setInt(i);
return f;
}
then initialize with bar(make_foo(3)).
You've sort of shot yourself in the foot by giving Foo a constructor but no int constructor. You might be better off adding an explicit constructor to Foo that takes an int.
Here is my code:
class Foo
{
public:
Foo(const char*);
};
class Bar
{
public:
Foo bu("adfds");
};
int main()
{
return 0;
}
Foo::Foo(const char* iLoc)
{ }
When I try to create a Foo class within the Bar class, I get the syntax error when trying to pass to the constructor. Why is this the case?
I prefer this to egrunin's answer as you don't have to track memory allocation.
class Bar
{
private:
Foo bu;
public:
Bar()
: bu("adfds")
{
}
};
You can't initialize bu in the class declaration. Is this what you want?
class Bar
{
public:
Foo *bu;
Bar() {
bu = new Foo("adfds");
}
};
Edit
As pointed out in the comments, here's a way of doing it without making bu a pointer:
class Bar : bu("adfds")
{
public:
Foo bu;
};