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.
Related
This question already has answers here:
What are the rules for calling the base class constructor?
(10 answers)
Closed 1 year ago.
#include <iostream>
using namespace std;
class A{
public:
A(){
cout << "Hello World";
}
};
class B:public A{
public:
B(){
cout << "World";
}
};
int main(){
B obj1;
return 0;
}
Why does this program print Hello WorldWorld, shouldn't it print World because I have created object of class B, so why is the constructor of A being called?
Conceptually, a base class becomes an unnamed sub object in the derived class, whose members are available in the same scope without extra qualification, and must be initialized.
You cannot avoid that initialization - which means a relevant constructor will be called or if it cannot be constructed then compiler will not allow you to inherit.
What you probably mean is whether the constructor should have overridden the base version, the simple answer is it cannot. If you want that effect - which will not work in constructors in a common sense way - you need to use virtual functions and overriding.
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.
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.
This question already has answers here:
Why is there no call to the constructor? [duplicate]
(3 answers)
Most vexing parse
(1 answer)
Closed 9 years ago.
#include <iostream>
class Base
{
public:
int id;
};
int main()
{
Base b();
b.id = 1;
}
What is wrong with the object creation in the code above? What is the difference between Base b() and Base b?
This
Base b();
is parsed as a function declaration of a function called b() that returns a Base object. You need this:
Base b;
This will instantiate a Base object and call its default constructor. Note that this will not zero initialize base::id. You can fix this by providing a default constructor that does that:
class Base
{
public:
Base() : id(0) {}
int id;
};
and instantiate in the same way:
Base b;
The problem is that you are not instantiating an object, but rather declaring a function. This:
Base b(); // Function declaration! (not what you want)
Declares a function b() that returns an object of type Base and accepts no argument. Therefore, when you later try to access the member id, the compiler emits an error, because functions do not have members:
b.id = 1; // ERROR! b is a function, accessing member "id" makes no sense
If you want to create an instance of Base, instead, just remove the parentheses:
Base b; // Object instantiation! (what you want)
Notice that in C++11 you can use the uniform initialization syntax to create an instance of a class pretty much the way you were trying to do, but with curly braces instead of parentheses:
Base b{}; // Object instantiation! (what you want, in C++11)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I call ::std::make_shared on a class with only protected or private constructors?
I want to create a shared pointer to a class, and have a factory method that returns it while keeping the constructor\destructor protected. since the shared pointer can't access the the constructor or the destructor, I get compiler errors.
I am using llvm 4.1, but I am looking for a solution that can be compiler independent (besides making the constructor\destructor public).
this is a code sample:
class Foo
{
public:
static std::shared_ptr<Foo> getSharedPointer()
{
return std::make_shared<Foo>();
}
protected:
Foo(int x){}
~Foo(){}
};
any Ideas?
Just allocate the pointer yourself instead of calling make_shared:
static std::shared_ptr<Foo> getSharedPointer()
{
return std::shared_ptr<Foo>(new Foo);
}
Note, however, that this would require making the destructor public.