Difference in constructors with X() = delete; and private X(); [duplicate] - c++

This question already has answers here:
Which is the difference between declaring a constructor private and =delete?
(7 answers)
Closed 7 years ago.
Let us assume we have a class X and we want wo explicitly forbid, let say the standard constructor. I used for a long time in the Header file:
private:
X(); // 1.
so, that the contructor was disabled outside the class, so for anybody. But recently I have learned that in C++11 follwoing was recommended:
X() = delete; // 2.
Both would achive my wish to forbid the standard contructor.
But what is the exact difference bewteen them? Why would C++11 recommend the last one? Are there any other flags, signals set in the 2. way?

Example 1 was the way to do it before we had = delete which came out in C++11. Now that we have = delete this will completely get rid of the constructor. With making the constructor private you could still use that constructor in a member function where if you try to default an object in a member function with = delete it will be a compiler error.
#include <iostream>
class Foo
{
Foo();
public:
static void SomeFunc() { Foo f; }
};
class Bar
{
public:
Bar() = delete;
static void SomeFunc() { Bar b; }
};
int main()
{
Foo::SomeFunc(); // will compile
Bar::SomeFunc(); // compiler error
}
Live Example

The former is kind of a hack. A friend class could still call the constructor (and you'd get an error at link-time unless you actually defined it as well).
The latter actually prevents its auto-generation so it's really not there.

Related

Can't access private constructor from a friend class [duplicate]

This question already has answers here:
make_unique cannot access private constructor in static member
(2 answers)
How to make std::make_unique a friend of my class
(1 answer)
Closed 7 months ago.
In the following code snippet, g++ compiler outputs the following error:
error: ‘B::B(const string&)’ is private within this context 857 |
{ return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); }
Commenting out the line where smart pointers are used seem to work. However, I'm not sure why it works for the other cases, and still not work for the smart pointer case.
#include <memory>
#include <iostream>
#include "string"
class A;
class B
{
friend class A;
B(const std::string& dummyString) { std::cout << dummyString << std::endl; }
};
class A
{
public:
A()
{
B b("dummy1");
B* pB1 = new B("dummy2");
std::unique_ptr<B> pB2 = std::make_unique<B>("dummy3");
}
};
int main()
{
A a;
}
The problem is that make_unique which is supposed to construct an instance of B is not a friend of B. Therefore it does not have access to B's private constructor.
You can use the following to achieve something similar:
std::unique_ptr<B> pB2 = std::unique_ptr<B>(new B("dummy3"));
In general it is advised to prefer make_unique to calling new yourself, and I do not encourage it in any way (see here: Differences between std::make_unique and std::unique_ptr with new).
But if you are bound to this specific class hirarchy it will solve your issue.
The problem is that make_unique internally uses the private constructor B::B(const std::string& ). But since make_unique itself is not a friend of A, we get the mentioned error.
To solve this you can either get rid of make_unique and directly use unique_ptr with new as shown here or make the ctor public.

Defining Function in c++ in different style [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Variables After the Colon in a Constructor
C++ constructor syntax question (noob)
I have some C++ code here:
class demo
{
private:
unsigned char len, *dat;
public:
demo(unsigned char le = 5, unsigned char default) : len(le)
{
dat = new char[len];
for (int i = 0; i <= le; i++)
dat[i] = default;
}
void ~demo(void)
{
delete [] *dat;
}
};
class newdemo : public demo
{
private:
int *dat1;
public:
newdemo(void) : demo(0, 0)
{
*dat1 = 0;
return 0;
}
};
My question is, what are the : len(le) and : demo(0, 0) called?
Is it something to do with inheritance?
As others have said, it's an initialisation list. You can use it for two things:
Calling base class constructors
Initialising member variables before the body of the constructor executes.
For case #1, I assume you understand inheritance (if that's not the case, let me know in the comments). So you are simply calling the constructor of your base class.
For case #2, the question may be asked: "Why not just initialise it in the body of the constructor?" The importance of the initialisation lists is particularly evident for const members. For instance, take a look at this situation, where I want to initialise m_val based on the constructor parameter:
class Demo
{
Demo(int& val)
{
m_val = val;
}
private:
const int& m_val;
};
By the C++ specification, this is illegal. We cannot change the value of a const variable in the constructor, because it is marked as const. So you can use the initialisation list:
class Demo
{
Demo(int& val) : m_val(val)
{
}
private:
const int& m_val;
};
That is the only time that you can change a const member variable. And as Michael noted in the comments section, it is also the only way to initialise a reference that is a class member.
Outside of using it to initialise const member variables, it seems to have been generally accepted as "the way" of initialising variables, so it's clear to other programmers reading your code.
This is called an initialization list. It is for passing arguments to the constructor of a parent class. Here is a good link explaining it: Initialization Lists in C++
It's called an initialization list. It initializes members before the body of the constructor executes.
It's called an initialization list. An initializer list is how you pass arguments to your member variables' constructors and for passing arguments to the parent class's constructor.
If you use = to assign in the constructor body, first the default constructor is called, then the assignment operator is called. This is a bit wasteful, and sometimes there's no equivalent assignment operator.
It means that len is not set using the default constructor. while the demo class is being constructed. For instance:
class Demo{
int foo;
public:
Demo(){ foo = 1;}
};
Would first place a value in foo before setting it to 1. It's slightly faster and more efficient.
You are calling the constructor of its base class, demo.

struct constructor error, why use default constructor function will call a error? [duplicate]

This question already has answers here:
Default constructor with empty brackets
(9 answers)
Closed 8 years ago.
#include <iostream>
using namespace std;
struct Foo{
Foo(){}
Foo(int){}
void fun(){}
};
void main()
{
Foo a(10);
a.fun();
Foo b();
b.fun();//error
Foo c = Foo(); // this is the right way to use default constructor?
c.fun();
}
The code has an error when compiling, because b is not a type of class, who can tell me what is b? And the meaning of Foo b()?
This problem is commonly known as C++ "most vexing parse".
Foo b();
This declares a function named b returning Foo.
It should be just;
Foo b;
This will declare a variable b of type Foo that will be default initialised (Foo has a default constructor). Foo c = Foo(); yes, this is an alternative default initialisation (copy initialisation) but it is generally used more with POD data types.
It is worth noting that with C++11 (uniform initialisation), the following will compile and is possibly an alternative for you
Foo b{};
But it does the same thing in this case (with respect to constructing b).
The right way should be:
Foo b;
You just declared a function named b.

Using default arguments in constructor [duplicate]

This question already has answers here:
default arguments in constructor
(5 answers)
Closed 9 years ago.
Is it possible to make constructor with default arguments.
Something like this
Object(int size = 1) {
//SMTH
}
I am trying to do like this in visual studio, but error apears.
Is it possible to create constructor with default arguments or it only remains to use overloading ?
EDIT
It is possible, sorry for posting this question, I am newbie in c++. The problem was that I was declaring default argument in source file (cpp) , I have changed my class like this and it works great.
class MyClass
{
public:
MyClass (int i = 0, std::string s = ""); // constructor declared
private:
int x;
int y;
std::string z;
};
MyClass :: MyClass(int i, std::string s) // constructor defined
{
x = 100;
y = i;
z = s;
}
Yes, it is possible to have constructors with default arguments.
Two caveats regarding your particular example:
Make sure you don't also have a no-args constructor as this would lead to ambiguity.
You might want to make this constructor explicit so that it's not used for implicit conversion from int to Object.

C++, What does the colon after a constructor mean? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicates:
Variables After the Colon in a Constructor
C++ constructor syntax question (noob)
I have some C++ code here:
class demo
{
private:
unsigned char len, *dat;
public:
demo(unsigned char le = 5, unsigned char default) : len(le)
{
dat = new char[len];
for (int i = 0; i <= le; i++)
dat[i] = default;
}
void ~demo(void)
{
delete [] *dat;
}
};
class newdemo : public demo
{
private:
int *dat1;
public:
newdemo(void) : demo(0, 0)
{
*dat1 = 0;
return 0;
}
};
My question is, what are the : len(le) and : demo(0, 0) called?
Is it something to do with inheritance?
As others have said, it's an initialisation list. You can use it for two things:
Calling base class constructors
Initialising member variables before the body of the constructor executes.
For case #1, I assume you understand inheritance (if that's not the case, let me know in the comments). So you are simply calling the constructor of your base class.
For case #2, the question may be asked: "Why not just initialise it in the body of the constructor?" The importance of the initialisation lists is particularly evident for const members. For instance, take a look at this situation, where I want to initialise m_val based on the constructor parameter:
class Demo
{
Demo(int& val)
{
m_val = val;
}
private:
const int& m_val;
};
By the C++ specification, this is illegal. We cannot change the value of a const variable in the constructor, because it is marked as const. So you can use the initialisation list:
class Demo
{
Demo(int& val) : m_val(val)
{
}
private:
const int& m_val;
};
That is the only time that you can change a const member variable. And as Michael noted in the comments section, it is also the only way to initialise a reference that is a class member.
Outside of using it to initialise const member variables, it seems to have been generally accepted as "the way" of initialising variables, so it's clear to other programmers reading your code.
This is called an initialization list. It is for passing arguments to the constructor of a parent class. Here is a good link explaining it: Initialization Lists in C++
It's called an initialization list. It initializes members before the body of the constructor executes.
It's called an initialization list. An initializer list is how you pass arguments to your member variables' constructors and for passing arguments to the parent class's constructor.
If you use = to assign in the constructor body, first the default constructor is called, then the assignment operator is called. This is a bit wasteful, and sometimes there's no equivalent assignment operator.
It means that len is not set using the default constructor. while the demo class is being constructed. For instance:
class Demo{
int foo;
public:
Demo(){ foo = 1;}
};
Would first place a value in foo before setting it to 1. It's slightly faster and more efficient.
You are calling the constructor of its base class, demo.