Passing functions as arguments not working inside a class - c++

Creating a Foo object passing func to constructor works just fine in this example:
int func(int a) { return a; }
struct Foo {
Foo( int (*func_ptr)(int) ) {};
};
Foo bar(func);
However attempting to create a Foo object inside another class does not:
class ThisIsCrap {
Foo doesntWork(func);
};
How can I create a Foo object inside a class like I can outside a class? On the bit that doesn't compile, the error is: "cannot resolve type 'func'"
Thanks in advance.

You can provide an initializer for non-static class data members with a default member initializer (DMI):
int func(int a) { return a; }
struct Foo { Foo(int (*)(int)) {}; };
class ThisIsGreat {
Foo one_way = func; // DMI with copy-initialization syntax
Foo another_way{func}; // DMI with list-initialization syntax
};
Or of course you could use a constructor:
class ThisIsSane {
ThisIsSane()
: third_way(func) // constructor-initializer list
{}
Foo third_way;
};
Language-lawyer note for pedants: In C++11, ThisIsGreat is not an aggregate; in C++14 it is.

1,000 thanks to Kerrek SB.
class ThisWorks {
Foo* working;
ThisWorks() {
working = new Foo(func);
}
}

Related

Can we declare constructor before member variables?

Can the constructer declared before the member variable alter its value?
I thought only the code below works,
struct test {
int a;
test(int t): a(t) {}
};
but I found the code below also works.
struct test {
test(int t): a(t) {}
int a;
};
Usually, in function, we cannot use the variable that is not declared. Why the code above is OK?
Actually in C++ there's an exception that there's no need for forward declaration of functions and variable of a class/struct.
You can see my such examples on the internet like this:
class foo
{
public:
foo(int x) : my_var(x) {}
private:
int my_var;
};
The above is 100% valid.
You can also call a function of a class before it is defined like:
class bar
{
public:
bar()
{
this->my_below_func();
}
int my_below_func()
{
return 1;
}
};
Always remember that these tricks aren't going to work outside C++ classes/structs, you will need forward declaration of your functions and variables.

Default initialize data members that are objects?

Why do you have to initialize object data members in the constructor and you can't default initialize them like with primitive types? Is it possible to initialize them like with primitive types?
Here's an example:
class foo {
int a;
public:
foo(int _a) :a(_a) {};
};
class bar {
string a = "asdf";//no error
int num = 1;//no error
foo x(1); //error, why?
foo z;
public:
bar(): z(1){}//no error
};
In-class initializers only work with the operator= syntax or with brace-initializer lists, not with the function style initialization. So
foo x{1};
instead of
foo x(1);
should do the trick.
In your case, you could also use
foo x = 1;
but that would break if foo's constructor taking a single int was explicit.
Permitting direct-initialization in class-definition would lead to difficulties in distinguishing from function declarations:
Consider:
struct k;
struct foo { foo(int x = 1){} };
class toto
{
static constexpr int k = 1;
foo x(1); // hm might be ok...
foo y(); // hm ... NOK , what y is ? an object or a function declaration?!?!
foo z(k); // problem .... this seems a fucntion definition?!!!
foo z{k}; // clear it is not a function definition
};
The proper way to do this is either:
foo f= 1;
or
foo f{1};
or
foo f = {1};

What method do you use to initialize member variables?

Suppose I have a class Foo, with a member variable that is a std::vector of floats, bar. I then create an instance of Foo, called foo. Let's say that I do not know the length of bar before the program runs, but at the point when foo's constructor is called, I know that it's length should be x.
There are three ways I can think of to initialize the length of bar, and I'm just wondering which of the three most people tend to use. I have ranked them in order of what I would consider to be "best practice", but I'm more curious about what method people "actually" use in practice. Sometimes I use methods which make the code clearer to follow, rather than necessarily following best practice...
bar is a private member, and I resize it during foo's constructor, e.g. Foo foo(x){bar.resize(x)};
bar is a private member, and I call foo.ResizeBar(x) which resizes bar internally, after creating foo.
bar is a public member, and I call foo.bar.resize(x), after creating foo.
Or, in code:
1.
class Foo
{
private:
std::vector<float> bar;
public:
Foo(int x)
{
bar.resize(x);
};
};
int main()
{
Foo foo(100);
return 0;
}
2.
class Foo
{
private:
std::vector<float> bar;
public:
Foo()
{
};
void ResizeBar(int x)
{
bar.resize(x);
};
};
int main()
{
Foo foo;
foo.ResizeBar(100);
return 0;
}
3.
class Foo
{
public:
std::vector<float> bar;
Foo()
{
};
};
int main()
{
Foo foo;
foo.bar.resize(100);
return 0;
}
The problem with all three of your methods is that you're needlessly invoking the default initializer for your vector, and then modifying the already initialized vector to suit your needs.
You should be invoking the correct initializer using the initializer list:
Foo::Foo(std::size_t x) : bar(x, 0) { }
The best method is not in the list of options you posted. The best method is to initialize bar using member initializer lists.
Foo::Foo(int x) : bar(x) {}

Calling a constructor with no parameters works, with a parameter doesn't. Why?

I have a class defined as follows:
class Foo {
private:
boolean feature;
public:
Foo(boolean feature) : feature(feature) {}
// ...
};
I'm trying to construct an instance, as a private property of another class:
class Bar {
private:
Foo foo(true);
// ...
};
This doesn't work. I get expected identifier before numeric constant on the line with the declaration. When I remove the parameter from Foo's constructor definition simply and ask for a Foo foo;, it works.
Why?
How do I define and declare an instance of Foo that takes a boolean parameter?
You can't use that initialisation syntax in a class member declaration; you can only initialise members with {} or =. The following should work (assuming support for C++11 or later):
Foo foo{true};
Foo foo = Foo(true);
The pre-C++11 way to do this is:
class Bar {
public:
Bar() : foo(true){} //initialization
private:
Foo foo; //no parameter
};
Bonus:
class Bar {
private:
Foo foo(); //<- This is a function declaration for a function
//named foo that takes no parameters returning a Foo.
//There is no Foo object declared here!
};

deleted default constructor headache

My c++ book says this (lippman, c++ primer, fifth ed., p. 508):
The synthesized default constructor is defined as deleted if the class ... has a const member whose type does not explicitly define a default constructor and that member does not have an in-class initializer. (emphesis mine)
Why then does this code produce an error?
class Foo {
Foo() { }
};
class Bar {
private:
const Foo foo;
};
int main() {
Bar f; //error: call to implicitly-deleted default constructor of 'Bar'
return 0;
}
The rule above seems to indicate that it should not be an error, because Foo does explicitly define a default constructor. Any ideas?
To fix your error. You need to make Foo::Foo() public.
class Foo
{
public:
Foo() { }
};
Otherwise I do believe it is private.
Is this what your looking for?
The default constructor is omitted when a a class construction isn't trivial.
That in general means that either there is an explicit constructor that receives parameters (and then you can't assume that it can be constructed without those parameters)
Or if one of the members or base classes need to be initiated in construction (They themselves don't have a trivial constructor)
I think that this should work
class Foo {
public:
Foo() { }
};
class Bar {
public:
Bar() : foo() {}
private:
const Foo foo;
};