Should SomeClass* initialEl = new SomeClass[5]; necessarily compile, assuming SomeClass does not have a non-publicly declared default constructor? Consider:
/*
* SomeClass.h
*
*/
#ifndef SOMECLASS_H_
#define SOMECLASS_H_
class SomeClass
{
public:
SomeClass(int){}
~SomeClass(){}
};
#endif /* SOMECLASS_H_ */
/*
* main.cpp
*
*/
#include "SomeClass.h"
int main()
{
SomeClass* initialEl = new SomeClass[5];
delete[] initialEl;
return 0;
}
Assuming SomeClass has a publicly accessible default constructor, yes.
Note that there is a difference between
having a publicly accessible default constructor (what i said) and
not having a non-publicly declared default constructor (what you said)
For the following class 2. is true but 1. is not:
class A {
SomeClass(const SomeClass&) {}
};
This is due to §12.1/5 (C++03):
If there is no user-declared constructor for class X, a default constructor is implicitly declared.
An implicitly-declared default constructor is an inline public member of its class.
With your update, SomeClass doesn't have a default constructor. You didn't declare one and because you have declared another constructor the compiler won't declare it implicitly either.
If you need one you have to implement it yourself:
class A {
public:
SomeClass(int) {}
SomeClass() {}
};
Or let another constructor qualify as a default constructor:
class A {
public:
SomeClass(int=0) {}
};
No, it won't compile without a default constructor. There is no compiler-generated default constructor in this case, because you have defined another constructor. "The compiler will try to generate one if needed and if the user hasn't declared other constructors." -- The C++ Programming Language, Stroustrup
If you really want to use new SomeClass[5], you'll have to provide a default constructor as well.
Related
Assume I have class Member that does not have neither a default constructor nor a copy constructor, and it gets created by a third party API as with a function.
I have the declarations
Member CreateMember(string str);
class MyClass {
Member my_member;
public:
MyClass(){
my_member = CreateMember("I am a parameter");
}
}
Since the class Member has no default constructor, the above declaration doesn't work, as there is no way to initialize the member.
I also cannot declare it as a pointer, since the lack of copy constructor means I can't call new Member(my_member).
I am at a loss here, any suggestions?
Use member initializer lists:
Member CreateMember(string str);
class MyClass {
Member my_member;
public:
MyClass()
: my_member(CreateMember("I am a parameter"))
{
}
};
This does not work
When I don't have a blank constructor in my class the code will not run causing an error saying no default constructor exists for class.
#include <iostream>
class myClass
{
public:
myClass(int val)
:x(val)
{}
private:
int x;
};
int main()
{
myClass random;
return 0;
}
This works
#include <iostream>
class myClass
{
public:
myClass(int val)
:x(val)
{}
myClass()
{}
private:
int x;
};
int main()
{
myClass random;
return 0;
}
This is because when you try to instantiate the object myClass random, you are trying to invoke the default constructor which you do not have.
If you changed it to myClass random(3)( basically trying to invoke the constructor that you have), you would see that the compiler would have no problems.
If you want myClass random to compile fine, then you must have a default constructor in your class.
Once you declare a constructor in a class (any constructor), the compiler won't automatically generate a default constructor for you (this is what you're calling the blank constructor).
If you don't want to implement the default constructor (generally a good idea if you just want the default behavior), you can tell the compiler to generate it for you as of C++11.
class myClass {
public:
myClass(int val)
:x(val)
{}
myClass() = default; // the compiler handles the implementation
private:
int x;
};
In the first case you have defined a parameterized constructor. When a constructor is defined the compiler now does not automatically define a default constructor like before.
If no constructor is defined the compiler automatically defines a default constructor but if another constructor is defined the compiler will not do so.
i.e. in first case a default constructor does not exist. In the second case you have defined one and hence has no errors.
See default constructor.
If no user-declared constructors of any kind are provided for a class type, the compiler will always declare a default constructor as an inline public member of its class.
However, there's a constuctor declared in your class, thus the compiler won't declare a default constructor. You have to explicitly declare one yourself.
In an attempt to answer another question, I came up with a scheme to force children of a CRTP base class to accept a particular type as a parameter in their constructors: make the parameter type's constructor private, assign the CRTP base class as a friend, and declare the parameter type as a parameter for the base class constructor as well.
However, when I tried to demonstrate that this scheme provided the desired protections via access violations, I found that even though the parameter type's constructor was private, the child class was able to construct it:
template <typename T>
class SingletonBase {
protected: class P { friend class SingletonBase<T>; P() = default; };
public:
SingletonBase(P) {}
};
class Logger: public SingletonBase<Logger> {
using BASE = SingletonBase<Logger>;
public:
Logger() : BASE{P{}} {} // WHY NO ACCESS VIOLATION?
};
This compiles without error, even though I'd expect an access violation. Why?
Does “friending” the base class in CRTP inheritance affect the child class as well?
No, of course not. Friendship is not inherited. To illustrate the issue,
Firstly, P::P() is a defaulted default constructor, it's a trivial default constructor.
Secondly, P{} is value initialization (since C++11),
(emphasis mine)
2) if T is a class type with a default constructor that is neither user-provided nor deleted (that is, it may be a class with an implicitly-defined or defaulted default constructor), the object is zero-initialized and then it is default-initialized if it has a non-trivial default constructor;
Note it'll be only zero initialized here, not default initializated. The private default constructor of P won't be invoked at all.
If T is an non-union class type, all base classes and non-static data members are zero-initialized, and all padding is initialized to zero bits. The constructors, if any, are ignored.
If you change it to default initialization explicitly, you'll get the access violation error.
Logger() : BASE{P()} {} // error: calling a private constructor of class 'SingletonBase<Logger>::P
// ~~
A simplified demonstration
class X { X() = default; };
int main()
{
X x1{}; // fine
X x2; // error: calling a private constructor of class 'X'
}
LIVE
Solution
You can provide a user-defined default constructor, which is a non-trivial constructor, to change the behavior of value-initialization.
template <typename T>
class SingletonBase {
protected:
class P {
friend class SingletonBase<T>;
P() {} // user-defined default constructor
};
public:
SingletonBase(P) {}
};
class Logger: public SingletonBase<Logger> {
using BASE = SingletonBase<Logger>;
public:
Logger() : BASE{P{}} {} // error: calling a private constructor of class 'SingletonBase<Logger>::P'
};
What you have done has nothing to do with your friend statement!
If you remove your friend the code compiles also fine!
That is because a default constructor for an empty class is public:
From C++11 standard:
If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted. An implicitly-declared default constructor is an inline public member of its class.
If you have no default constructor like this:
template <typename T>
class SingletonBase
{
protected:
class P
{
friend class SingletonBase<T>;
P(int){ }
};
public:
SingletonBase(P) {}
};
class Logger: public SingletonBase<Logger>
{
using BASE = SingletonBase<Logger>;
public:
Logger() : BASE(P{1}) {} // WHY NO ACCESS VIOLATION?
};
You will get the "access" violation and you see that your friend did not work!:
main.cpp: In constructor 'Logger::Logger()':
main.cpp:10:17: error: 'SingletonBase<T>::P::P(int) [with T = Logger]' is private
P(int){ }
^
main.cpp:22:28: error: within this context
Logger() : BASE(P{1}) {} // WHY NO ACCESS VIOLATION?
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;
};
#include <iostream>
#include <conio.h>
using namespace std;
class Base
{
int a;
public:
Base(const Base & b)
{
cout<<"inside constructor"<<endl;
}
};
int main()
{
Base b1;
getch();
return 0;
}
This gives an error. no matching function for call to `Base::Base()'
Why?
The default constructor is only generated if you don't declare any constructors. It's assumed that if you're defining a constructor of your own, then you can also decide whether you want a no-args constructor, and if so define that too.
In C++0x, there will be an explicit syntax for saying you want the default constructor:
struct Foo {
Foo() = default;
... other constructors ...
};
It does not hide the default constructor, but declaring any constructor in your class inhibits the compiler from generating a default constructor, where any includes the copy constructor.
The rationale for inhibiting the generation of the default constructor if any other constructor is present is based on the assumption that if you need special initialization in one case, the implicitly generated default constructor is most probably inappropriate.