I have a class called Foo with a constructor that needs arguments, and a other class Bar with a Foo private variable
class Foo
{
public:
Foo(string);
}
class Bar
{
public:
Bar() { this->foo = Foo("test") }
private:
Foo foo;
}
However, when I try to compile this, I get a compile error that there is no Foo::Foo() constructor. It looks like the private variable foo in class Bar gets initialized before getting a value assigned in the constructor.
How can I have a private foo variable that waits to gets initialized in my constructor?
You need to use an initializer list. If you don't, your code will call the default constructor for that object.
Bar::Bar() : foo("test") {
// stuff
}
Use an initializer list:
Bar() : foo("test") {}
BTW, in C++ reasons to use this-> are rare (and often indicate other problems).
Related
I have a class Foo that references Bar:
class Foo {
Bar &bar;
};
and bar requires an int& to be constructed:
Class Bar {
Bar(int& required_int);
}
I want to be able to initialize Bar when I initalize Foo, but I cannot seem to do so using either of the following:
Foo::Foo(int &my_int) : bar(my_int) {
//...
}
Foo::Foo(int &my_int) : bar(new Bar(my_int)) {
//...
}
Because the compiler complains that whatever is inside bar(...) must be an lvalue. Is this initalization chaining possible? I don't see how bar(...) could ever contain an lvalue if my instance of Bar doesn't exist yet.
class Foo {
Bar & bar;
};
Here bar can only refer to an existing Bar object as it's a reference. You cannot initialize it yourself in Foo class. So, a valid ctor would be similar to this:
Foo::Foo(Bar & existingBar) : bar(existingBar){}
If you want Foo class to have its own independent Bar object, then remove the reference and initialize it like you're doing already.
I have a class with a hidden default constructor to force the use of a constructor taking parameters. Another class is using 2 instances of the class:
typedef struct { ... } BAZ;
class Foo {
private:
Foo(void) {}
public:
Foo(BAZ a) { ... }
};
class Bar {
private:
Foo foo1;
Foo foo2;
Bar(void) {}
public:
Bar(BAZ a, BAZ b) : foo1(a), foo2(b) { ... }
};
The most obvious is that the declaration of the variables foo1 and foo2 will call the default Foo constructor, but since it is private it can't and will give a compiler error.
Is there a way to prevent it from trying the default Foo constructor and just wait for the Bar constructor to initialise them instead?
I want to avoid the use of the new keyword (which would solve the whole problem).
EDIT:
It seems like people have a hard time to understand the question and dilemma. I will try to explain:
I want to force the use of a Foo(BAZ) constructor meaning that any attempt to use the Foo(void) constructor will generate an error.
To hide the default constructor it is declared as a private member. If someone try to use the default constructor Foo() it will give an intentional error.
To not declare the default constructor and only declare Foo(BAZ) is not preventing the compiler to create a public default constructor. It gives no error if I declare it Foo(). So far it works fine and as intended.
The second class Bar have two instances of Foo but when Bar is instanced these Foo members will be called with the default (hidden) constructor and generate an error. Then in the Bar constructor, these two instances will be initialized with the correct public constructor Bar(BAZ a, BAZ b) : foo1(a), foo2(b). This is what I want.
Is there a way to prevent it from calling Foo default constructor when Bar is initialized, so the Bar constructor can use the correct Foo constructor?
The new solution works because the default constructor is never called:
BAZ a = {...}
Foo *foo1 = new Foo(a);
I hope this makes it more clear.
EDIT2: SOLVED
The error wasn't in the hidden Foo constructor, it was the hidden Bar constructor trying to use the hidden default Foo constructors.
Bar(void) : Foo(BAZ{}), Foo(BAZ{}) {}
Solved it.
EDIT3:
The real problem seems to have been in the development tool. After restart and manually clearing the cache it worked as the C++14 standard intended.
the declaration of the variables foo1 and foo2 will call the default
Foo constructor
No. Declaring these member variables only says that they are members. It doesn't say anything about how they will be constructed. That's the job of the constructor(s) of the class that uses them.
Bar(BAZ a, BAZ b) : foo1(a), foo2(b) { ... }
Fine so far: this constructor constructs the foo1 and foo2 members using the constructor Foo(Baz).
Bar(void) {}
This is the problem: it attempts to construct the foo1 and foo2 members with the default constructor for Foo. Since that constructor is not accessible (that's the correct term; it is not hidden), you get an error. There are at least three solutions:
1:
Bar() : foo1(Baz()), foo2(Baz()) {}
This uses the constructor that takes Baz.
2:
Bar() = delete;
This makes the default constructor for Bar not exist, so it doesn't try to use the default constructor for Foo.
3:
Just don't do it. If you don't write a default constructor but you do write another one, the compiler won't generate a default constructor.
Don't hide constructors. Don't declare them in the first place.
typedef struct { ... } BAZ;
class Foo {
public:
Foo(BAZ a) { ... }
};
class Bar {
private:
Foo foo1;
Foo foo2;
public:
Bar(BAZ a, BAZ b) : foo1(a), foo2(b) { ... }
};
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!
};
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;
};
Why do we declare constructor's as public?
Constructors are the way objects are created. If your constructor were not public, then it couldn't be used to construct a new object from outside the class.
Note that sometimes a non-public constructor is useful, for example:
class foo
{
public:
static foo make_foo(int i)
{
// only functions of foo can use that constructor,
// because it's private; return a foo
return foo(i);
}
private:
foo(int i) { /* construct */ }
};
Now foo can only be created via the function make_foo, for whatever reason.
In the below code line, initialization should take place via constructor. If the constructor is private in this case, how is it going to be accessed outside the class scope. Moreover, foo::foo(int num) is going to be called by default while instantiation of obj.
foo *obj = new foo(5);
If you don't you will not be able to construct the object from other objects.