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.
Related
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) { ... }
};
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;
};
What's the diference between use:
static Foo foo;
// ...
foo.func();
And:
Foo& GetFoo(void)
{
static Foo foo;
return foo;
}
// ...
GetFoo().func();
Which is better?
The principal difference is when construction occurs. In the first case, it occurs sometime before main() begins. In the second case, it occurs during the first call to GetFoo().
It is possible, in the first case, for code to (illegally) use foo prior to its initialization. That is not possible in the second case.
A GetFoo is generally used when you don't want copies of your class/object.
For example:
class Foo
{
private:
Foo(){};
~Foo();
public:
static Foo* GetFoo(void)
{
static Foo foo;
return &foo;
}
int singleobject;
};
You can externally access singleobject via Foo::GetFoo()->sinlgeobject. The private constructors and destructors avoid your class getting copies created.
For the use of static Foo foo, you must have public constructors declared which means you are always accessing your class by it, but your class will also be able to get copies.
As far as I know it is not possible to call the constructor of the base class. The only way I know is this:
MyClass::MyClass(/* args */) : Base(/* args */)
{
// ...
}
but this would invoke the constructor at the beginning.
Is there any way to call it somewhere else in the constructor? Something like this:
MyClass::MyClass(/* args */)
{
// ... instructions
Base::Base(/* args */);
// ... other_instructions
}
According to this What are the rules for calling the superclass constructor? question I understand there is no way but I read here and I guessed it was possible, but if I try I get:
error: invalid use of 'class Base'.
Am I doing something wrong? Is it possible to do this some way or is there any other possible solution to this need?
Thanks!
EDIT: I understand I forgot a key point: the base class is part of a framework, and therefore it would be good not to have to modify it, if possible.
If the base class constructor takes at least one argument, you could use a helper function like this:
int DoStuffBeforeCtorAndForwardInt(int arg, Foo foo)
{
DoStuff(arg, foo);
return arg;
}
MyClass::MyClass(int arg, Foo foo)
: Base(DoStuffBeforeCtorAndForwardInt(arg, foo))
{
// ...
}
If you want to default-initialize the base class, you could use the copy-ctor to copy a default initialized base class instance:
Base DoStuffBeforeCtorAndReturnDefaultBase(int arg, Foo foo)
{
DoStuff(arg, foo);
return Base();
}
MyClass::MyClass(int arg, Foo foo)
: Base(DoStuffBeforeCtorAndReturnDefaultBase(arg, foo))
{
// ...
}
Or, if Base doesn't have to be the first base class, you could derive MyClass from a helper class:
MyClass::MyClass(/* ... */)
: DoStuffHelperClass(/* ... */),
Base(/* ... */)
{
// ...
}
All of the above require that the "stuff" you do does not depend on the object that's about to be initialized (i.e. the functions can't safely be member functions and you cannot safely pass this as an argument to them either).
That means you can do some logging or similar, but then again you could also do that after the base class has been initialized.
(EDIT except with the DoStuffHelperClass solution, you can of course have members in DoStuffHelperClass, access them and what not)
Although I have to say that I can't recall ever using/needing/wanting something like that. It's quite probable that there is another (preferable) solution for what you're trying to do.
Use the base-from-member idiom to run your code before the ctor of the "real" base class (which is Base):
struct Base {
Base(string, int);
};
struct DerivedDetail {
DerivedDetail() {
value = compute_some_value();
value += more();
value += etc();
other = even_more_code(value);
}
string value;
int other;
};
struct Derived : private DerivedDetail, Base {
Derived() : Base(value, other) {}
// In particular, note you can still use this->value and just
// ignore that it is from a base, yet this->value is still private
// within Derived.
};
This works even if you don't have actual members you want in DerivedDetail. If you give more specifics on what you must do before the Base's ctor, then I can give a better example.
The base class is always fully constructed before construction of your own class begins. If you need to make a change to the state of the base class, you have to do that explicitly after it has been constructed.
Example:
MyClass::MyClass()
{
// Implicit call to Base::Base()
int result = computeSomething();
Base::setResult(result);
// ...
}
Besides the already written solutions, you can also use a static constructor function and make the contructor of MyClass private.
class QtBase{
// ...
};
class MyClass : public QtBase{
public:
// copy ctor public
MyClass(MyClass const& other);
static MyClass Create(/*args*/){
// do what needs to be done
int idata;
float fdata;
// work with idata and fdata as if they were members of MyClass
return MyClass(idata,fdata); // finally make them members
}
static MyClass* New(/*args*/){
int idata;
float fdata;
// work with idata and fdata as if they were members of MyClass
return new MyClass(idata,fdata); // finally make them members
}
private:
// ctor private
MyClass(int a_idata, float a_fdata)
: idata(a_idata)
, fdata(a_fdata)
{}
int idata;
float fdata;
};
Now you would have to create instances of MyClass either as:
MyClass obj = MyClass::Create(/*args*/);
or
MyClass* ptr = MyClass::New(/*args*/);
no, because it will not be type safe.
consider you have: a class A and a variable A.var.
now consider B inherits from A, and uses var before A was initialized. you will get a run time error! the language wants to prevent this, thus superclass constructor must be initialized first.
No, you can't do it that way, as other have described in their previous answers.
Your only chance is composition, IOW that MyClass uses Base class as a member field:
class MyClass {
public:
/** the methods... */
private:
Base* _base;
};
so you can initialize _base later, when you have the needed info. I don't know if this can apply to your scenario, anyway.
No. It is not possible, because the order of constructor calls is strictly defined by the standard. Base class ctor has to be executed before the derive class ctor can be executed.
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).