why does my class only work with two constructors c++ - c++

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.

Related

In what situation would C++11 = default constructor be different from a constructor taking no parameters and an empty body?

I know that if a parametrized constructor is provided, the implicit default constructor is not generated.
If we have a constructor taking no parameters and an empty body it can play the role of a default constructor.
class Box {
public:
Box(int value) : x(value) {} // parametrized constructor
Box() {} // default constructor
private:
int x;
};
In C++11 we can write = default to specify that we want the implicitly generated default constructor to be present, even if we have already a parametrized constructor.
class Box {
public:
Box(int value) : x(value) {} // parametrized constructor
Box() = default;
private:
int x;
};
I am wondering, is there a difference between these two syntaxes for specifying a default constructor explicitly? Are they equivalent or not? Is a constructor taking no parameters and no body really a default constructor or is it something else?
I want to ask, can there be a situation in which the constructor taking no parameters and no body have a different behavior than the C++11 = default constructor? Obscure and arcane examples are welcome.
One difference is that if you =default the default constructor, the type becomes a literal type, which makes objects of the type able to be used as constexpr variables.
class Box {
// ...
Box() = default;
};
constexpr Box box{}; // ok
class Box {
// ...
Box() {}
};
constexpr Box box{}; // error
Here's a demo.

Default ctor not generated when there's a template copy ctor

template<class T>
class MyClass {
public:
//MyClass() = default;
template<class X>
MyClass(MyClass<X>& other)
{
val = other.getVal();
}
T getVal()
{
return val;
}
private:
T val;
};
main()
{
MyClass<double> xd; //this one causing the problem
MyClass<double> xd1(xd); //this one is fine
MyClass<int> xi(xd);
}
This code will not compile.
But if you uncomment MyClass() = default, then everything is fine.
As far as I remember the template ctor not preventing compiler from generating the default ctor and copy ctor as well.
And indeed the compiler complaining only when trying to create object through the default ctor, but not for copy construction (which in this case is compiler generated)
The code was compiled with g++ 5.4.0 and 7.1.0. Same behavior with both
This is not a copy constructor:
template<class X>
MyClass(MyClass<X>& other) {
val = other.getVal();
}
This is a constructor taking a mutable lvalue reference to many different type than this class.
This is a copy constructor:
MyClass(const MyClass&) {
// ...
}
You can test if a function bus a special function by trying to put = default after it's signature. If the compiler complains about your misuse of defaulted functions, you function is not a special one.
When any other constructor than special constructors is added, the default constructor is not generated. That function being a template makes no different effect than a non template one. In that case, MyClass() = default is indeed required.
From cppreference:
If no user-declared constructors of any kind are provided for a class type (struct, class, or union), the compiler will always declare a default constructor as an inline public member of its class.
On the contrary, if a user provided constructor is declared, no implicitly defined default constructor is defined.
And from [class.ctor]§5:
A default constructor for a class X is a constructor of class X that can be called without an argument. If there is no user-declared constructor for class X, a constructor having no parameters is implicitly declared as defaulted (8.4).
Since your class has a user provided constructor, no implicitly declared/defined constructor is generated. Again, you can always force it's generation with = default.

protected inheritance error

#include<iostream>
using namespace std;
class base
{
protected:
int a;
public:
base(int i)
{
a=i;
}
};
class derived :protected base
{
public:
derived(){}
void show()
{
cout<<a;
}
};
int main()
{
base obj(2);
derived obj1;
obj1.show();
return 0;
}
Why is this program giving error as In constructor derived::derived():
error: no matching function for call to base::base()
Please explain. As i have read in stackoverflow that in case of inheriting as protected, protected members of base class became protected member of derived class. If I am wrong then please share a good link to clear my misconception
Once you define a constructor for any class, the compiler does not generate the default constructor for that class.
You define the parameterized constructor(base(int i)) for base and hence the compiler does not generate the no argument constructor for base.
Resolution:
You will need to define a constructor taking no arguments for base yourself.
Add this to your base class:
base():a(0)
{
}
EDIT:
Is it needed to define default constructor to every class? Or is it necessary to have the constructor that matches the derived type also present in base type?
The answer to both is NO.
The purpose of constructors in C++ is to initialize the member variables of the class inside the constructor. As you understand the compiler generates the default constructor(constructor which takes no arguments) for every class.
But there is a catch, If you yourself define (any)constructor(one with parameters or without) for your class, the compiler does not generate the default constructor for that anymore. The compiler reasoning here is "Huh, this user writes a constrcutor for his class himself, so probably he needs to do something special in the constructor which I cannot do or understand", armed with this reasoning the compiler just does not generate the default no argument constructor anymore.
Your code above and you assume the presence of the default no argument constructor(When derived class object is created). But since you already defined one constructor for your base class the compiler has applied its reasoning and now it refuses to generate any default argument constructor for your base class. Thus the absence of the no argument constructor in the base class results in the compiler error.
You must give a value to the base constructor:
class Derived : protected base
{
public:
Derived() : base(0)
{
}
};
Depending on your implementation, give the value to the base constructor. However, you may want the Derived constructor to take also int as an argument, and then pass it to the base one.
You need to implement an empty constructor in base or invoke the defined base(int) constructor explicitly from derived c-tor. Without it, when derived c'tor is activated,
it is trying to invoke base() [empty c'tor], and it does not exist, and you get your error.
You haven't defined a default constructor for Base..
When you instantiate an instance of Derived, it will call the Derived() constructor, which will in turn try to call the Base() default constructur which doesn't exist as you haven't defined it.
You can either declare an empty constructor for base Base::Base() or call the existing one as below:
#include<iostream>
using namespace std;
class base
{
protected:
int a;
public:
base(int i)
{
a=i;
}
};
class derived :protected base
{
derived(): Base(123) {} --this will call the Base(int i) constructor)
void show()
{
cout<<a;
}
};
int main()
{
base obj(2);
derived obj1;
obj1.show();
return 0;
}

Why does copy constructor hide the default constructor in C++?

#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.

SomeClass* initialEl = new SomeClass[5];

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.